首页技术栈归档照片墙音乐日记随想收藏夹友链留言关于

Spring Security 安全配置

写作时间:2026-07-07
   //Spring自带的默认加密器  
   //简单的MD5加密容易被暴力破解   
     String s = DigestUtils.md5Hex("123456");
        System.out.println(s);
        System.out.println(Md5Crypt.md5Crypt("123456".getBytes()));
        System.out.println(Md5Crypt.md5Crypt("123456".getBytes(),"$1$qqqqqqqq"));
       //采用Spring Boot的默认的一个盐值加密算法,每次都生成不同的加密字符
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        //$2a$10$GT0TjB5YK5Vx77Y.2N7hkuYZtYAjZjMlE6NWGE2Aar/7pk/Rmhf8S
        //$2a$10$cR3lis5HQQsQSSh8/c3L3ujIILXkVYmlw28vLA39xz4mHDN/NBVUi
        String encode = bCryptPasswordEncoder.encode("123456");  //加密算法
        boolean matches = bCryptPasswordEncoder.matches("123456", "$2a$10$GT0TjB5YK5Vx77Y.2N7hkuYZtYAjZjMlE6NWGE2Aar/7pk/Rmhf8S"); //解密

        System.out.println(encode+"==>" + matches);

一个简单的密码加密登录校验

    /**
     * 用户登录
     * @param vo
     * @return
     */
    @Override
    public MemberEntity login(MemberUserLoginVo vo) {
        String loginacct = vo.getLoginacct();
        String password = vo.getPassword();

        MemberDao memberDao= this.baseMapper;
        //手机号和用户名有一个匹配即可
        MemberEntity entity = memberDao.selectOne(new QueryWrapper<MemberEntity>()
                .eq("username", loginacct)
                .or().eq("mobile", loginacct));
        if (entity==null) {
            //登录失败
            return null;
        }else {
            //获取到数据的password 与我们加密的密码进行比较
            String passwordDb = entity.getPassword();
            BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
            //密码匹配
            boolean matches = passwordEncoder.matches(password, passwordDb);
            if (matches) {
                return entity;
            }else {
                return null;
            }

        }
    }

分布式session简单使用

官网:https://docs.spring.io/spring-session/docs/2.1.2.RELEASE/reference/html5/guides/boot-redis.html

导入依赖

<!--springSession 解决session共享问题-->
 <dependency>
     <groupId>org.springframework.session</groupId>
     <artifactId>spring-session-data-redis</artifactId>
 </dependency>

application.properties

spring.redis.port=6379
spring.redis.host=127.0.0.1

#设置共享方式为redis
spring.session.store-type=redis
#设置session过期时间为30分钟
server.servlet.session.timeout=30m

启动类

@SpringBootApplication
@EnableRedisHttpSession  //整合redis作为session存贮
public class GulimallAuthServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(GulimallAuthServerApplication.class, args);
    }

}

可以将session存储在公共模块中:直接在页面进行取出即可,假如有模块要用到session都要加入以配置进行取出即可

使用httpSession进行存储即可

    @PostMapping(value = "/login")
    public String login(UserLoginVo vo, RedirectAttributes attributes, HttpSession session) {

        //远程登录
        R login = memberFeignService.login(vo);

        if (login.getCode() == 0) {
            MemberResponseVo data = login.getData("data", new TypeReference<MemberResponseVo>() {});
            //TODo 1、默认发的令牌。session=dsajkdjL。作用域:当前域;(解决子域session共享问题)
            // T0Do 2、使用JsON的序列化方式来序列化对象数据到redis中
            session.setAttribute(LOGIN_USER,data);
            return "redirect:http://gulimall.com";
        } else {
            Map<String,String> errors = new HashMap<>();
            errors.put("msg",login.getData("msg",new TypeReference<String>(){}));
            attributes.addFlashAttribute("errors",errors);
            return "redirect:http://auth.gulimall.com/login.html";
        }
    }
}
  <a th:if="${session.loginUser != null}">欢迎, [[${session.loginUser.nickname}]]</a>

配置类,在登陆页面和商品服务都要加时配置类否则会取不出来

/**
 * 自定义session,放大作用域
 */

@Configuration
public class GulimallSessionConfig {

    @Bean
    public CookieSerializer cookieSerializer() {

        DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();

        //放大作用域
        cookieSerializer.setDomainName("gulimall.com");   //指定session的作用域 ,对应的域名 ,子域名  list.gulimall.com ,serch.gulimall.com 都能接收到父域名的数据
        cookieSerializer.setCookieName("GULISESSION");   //自定义的名称

        return cookieSerializer;
    }


    @Bean
    public RedisSerializer<Object> springSessionDefaultRedisSerializer() {
        return new GenericJackson2JsonRedisSerializer();
    }

}

单点登录流程图

在本机的hosts配置

#单点登录测试配置 127. 0.0.1 sso.com 127. 0.0.1 client1.com 127. 0.0.1 client2.com

单点登录服务端

LoginController

@Controller
public class LoginController {

    @Resource
    private RedisTemplate redisTemplate;

    @GetMapping("/userinfo")
    @ResponseBody
    public String userInfo(@RequestParam("token") String token){
        return (String) redisTemplate.opsForValue().get(token);
    }


    @GetMapping("/login.html")
    public String loginPage(@RequestParam("redirect_url") String url, Model model,
                            @CookieValue(value = "sso_token",required = false) String sso_token) {
        if (!StringUtils.isEmpty(sso_token)) {
            //如果cookie不为空是说明以前是有人登录过的,在浏览器留下的痕迹
            return "redirect:"+url+"?token="+sso_token;
        }
        //否则跳转到登录页面
        model.addAttribute("url",url);
        return "login";
    }

    @PostMapping("/doLogin")
    public String login(@RequestParam("username")String username,
                        @RequestParam("password") String password,
                        @RequestParam("redirect_url") String url,
                        HttpServletResponse response) {
        if (!StringUtils.isEmpty(username) && !StringUtils.isEmpty(password)) {
            //登录成功跳转,保存的用户保存起来
            String uuid = UUID.randomUUID().toString().replace("-", "");
            redisTemplate.opsForValue().set(uuid,username);
            Cookie sso_cookie = new Cookie("sso_token",uuid);
            response.addCookie(sso_cookie);
            return "redirect:" + url + "?token=" + uuid;
        }
        //登录失败跳转
        return "login";
    }

}

login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录页</title>
</head>
<body>
    <form action="/doLogin" method="post">
        用户名:<input type="text" name="username" /><br />
        密码:<input type="password" name="password" /><br />
        <input type="hidden" name="redirect_url" value="http://localhost:8081/employees" />
        <input type="submit" value="登录">
    </form>
</body>
</html>

application.properties

server.port=8080

spring.redis.port=6379
spring.redis.host=127.0.0.1

单点登录客户端1

HelloController

@Controller
public class HelloController {

    @Value("${sso.server.url}")
    private String ssoServerUrl;

    /**
     * 无需登录就可以访问
     * @return
     */
    @RequestMapping("/hello")
    @ResponseBody
    public String hello() {
        return "hello";
    }

    /**
     * 感知这次实在ssoserver登录成功跳回来的
     * @param model
     * @param session
     * token 只要去ssoserver登录成功就会回来带上
     * @return
     */
    @GetMapping("/employees")
    public String employees(Model model, HttpSession session,
                            @RequestParam(value = "token", required = false) String token){
        if (!StringUtils.isEmpty(token)) {
            //去ssoserver登录成功就会回来带上
            //TODO 1,去ssoserver获取当前的token真正对应的用户信息
            RestTemplate restTemplate=new RestTemplate();
            ResponseEntity<String> forEntity = restTemplate.getForEntity("http://sso.com:8080/userinfo?token=" + token, String.class);
            String body = forEntity.getBody();

            session.setAttribute("loginUser", body);
        }

        String loginUser = (String) session.getAttribute("loginUser");
        if (loginUser==null){
            //没有登录,跳转到登录服务器进行登录
            //跳转过去以后,使用url上的查询参数标识我们自己是哪个页面
            // redirect_urL=http://client1.com:8880/employees
            return "redirect:http://sso.com:8080/login.html?redirect_url=http://localhost:8081/employees";
        }else {
            ArrayList<String> employe = new ArrayList<>();
            employe.add("张三");
            employe.add("李四");
            model.addAttribute("emps",employe);
            return "list";
        }
    }
}

application.properties

server.port=8081

sso.server.url="http://sso.com:8080/login.html"

list.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>员工列表</title>
</head>
<body>
    <h1>欢迎:[[${session.loginUser}]]</h1>
    <ul>
        <li th:each="emp:${emps}">姓名:[[${emp}]]</li>
    </ul>
</body>
</html>

单点登录客户端2

HelloController

package com.yuan.gulimall.ssoclient.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpSession;
import javax.xml.ws.RespectBinding;
import java.util.ArrayList;

@Controller
public class HelloController {

    @Value("${sso.server.url}")
    private String ssoServerUrl;

    /**
     * 无需登录就可以访问
     * @return
     */
    @RequestMapping("/hello")
    @ResponseBody
    public String hello() {
        return "hello";
    }

    /**
     * 感知这次实在ssoserver登录成功跳回来的
     * @param model
     * @param session
     * token 只要去ssoserver登录成功就会回来带上
     * @return
     */
    @GetMapping("/boos")
    public String employees(Model model, HttpSession session,
                            @RequestParam(value = "token", required = false) String token){
        if (!StringUtils.isEmpty(token)) {
            //去ssoserver登录成功就会回来带上
            //TODO 1,去ssoserver获取当前的token真正对应的用户信息
            RestTemplate restTemplate=new RestTemplate();
            ResponseEntity<String> forEntity = restTemplate.getForEntity("http://sso.com:8080/userinfo?token=" + token, String.class);
            String body = forEntity.getBody();

            session.setAttribute("loginUser", body);
        }

        String loginUser = (String) session.getAttribute("loginUser");
        if (loginUser==null){
            //没有登录,跳转到登录服务器进行登录
            //跳转过去以后,使用url上的查询参数标识我们自己是哪个页面
            // redirect_urL=http://client1.com:8880/employees
            return "redirect:http://sso.com:8080/login.html?redirect_url=http://localhost:8082/boos";
        }else {
            ArrayList<String> employe = new ArrayList<>();
            employe.add("张三");
            employe.add("李四");
            model.addAttribute("emps",employe);
            return "list";
        }
    }
}

application.properties

server.port=8082

sso.server.url="http://sso.com:8080/login.html"

list.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>员工列表</title>
</head>
<body>
    <h1>欢迎:[[${session.loginUser}]]</h1>
    <ul>
        <li th:each="emp:${emps}">姓名:[[${emp}]]</li>
    </ul>
</body>
</html>
avatar

yuanyourdomain

写代码,做研究,记录生活。

RECOMMENDED

MyBatis 动态 SQL

2026-07-08

Nginx 基础入门

2026-07-08

Maven 多模块与私服

2026-07-08