Spring Security(百度云里有详细的文档)

从下图的6个方面去学习

image

一.Spring Security本质上是过滤器链。

1.导入security和springbootweb的依赖,就会开始生效,默认拦截全部请求,如果用户没有登录,跳转到内置登录页面。默认的用户名为user,密码在控制台打印。

2.自定义传入账号和密码1,他提供了 UserDetailsService 接口,而其返回值 UserDetails 也是一个接口,实现类有 User 类。使用时直接构造user类,传入账号密码和权限。

Spring Security 要求容器中必须有 PasswordEncoder 实例,所以当自定义登录逻辑时要求必须给容器注入PaswordEncoder 的bean对象。

3.自定义传入账号和密码2,PasswordEncoder 密码解析器是一个接口。

image
BCryptPasswordEncoder是官方推荐的解析器,实例化之后用encode方法加密,用matches方法判断密码是否正确。

//本来应该是把数据库里加密过的密码取出来,但是这里没连数据库,就先进行加密再放入user构造方法。
        String password = b.encode("123");
        User user = new User("admin", password,new ArrayList<>());
//        boolean matches = b.matches("123", password);
//        System.out.println(matches);

二.Oauth2第三方认证技术接口协议

1.以微信授权为例

image

2.Oauth2.0认证流程(官方)

image

3.Spring Security Oauth2授权码模式

1)导入spring-cloud-starter-oauth2等依赖

三.JSON Web Token(JWT)是一个开放的行业标准,用于在通信双方传递json对象

1.一个JWT实际上就是一个字符串,它由三部分组成,头部、载荷与签名

1)头部(Header)用于描述关于该JWT的最基本的信息,例如其类型(即JWT)以及签名所用的算法(如HMAC SHA256或RSA)等。

{
  "alg": "HS256",
  "typ": "JWT"
}

typ :是类型。
alg :签名的算法,这里使用的算法是HS256算法
一般我们会对头部的json字符串进行BASE64编码
2)负载(Payload)就是存放有效信息的地方
标准中注册的声明(建议但不强制使用)

iss: jwt签发者
sub: jwt所面向的用户
aud: 接收jwt的一方
exp: jwt的过期时间,这个过期时间必须要大于签发时间
nbf: 定义在什么时间之前,该jwt都是不可用的.
iat: jwt的签发时间
jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。

公共的声明
公共的声明可以添加任何的信息,一般添加用户的相关信息或其他业务需要的必要信息.但不建议添加敏感信息,
因为该部分在客户端可解密
私有的声明

{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022
}
其中 sub 是标准的声明, name 是自定义的声明(公共的或私有的)

3)签证、签名(signature)签证信息由三部分组成
1. header (base64后的)
2. payload (base64后的)
3. secret(盐,一定要保密)
将这三部分用.连接成一个完整的字符串,构成了最终的jwt:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaW
F0IjoxNTE2MjM5MDIyfQ.8HI-Lod0ncfVDnbKIPJJqLH998duF9DSDGkx3gRPNVI

三.JJWT简介,JJWT是一个提供端到端的JWT创建和验证的Java库。

      //创建一个JwtBuilder对象
      JwtBuilder jwtBuilder = Jwts.builder()
            //声明的标识{"jti":"888"}
           .setId("888")
            //主体,用户{"sub":"Rose"}
           .setSubject("Rose")
            //创建日期{"ita":"xxxxxx"}
           .setIssuedAt(new Date())
            //签名手段,参数1:算法,参数2:盐
           .signWith(SignatureAlgorithm.HS256,"xxxx");
      //设置过期时间一分钟
           .setExpiration(new Date(now + 60 * 1000))
      //获取jwt的token
      String token = jwtBuilder.compact();
      System.out.println(token);
      //三部分的base64解密
      System.out.println("--------------------");
      String[] split = token.split("\\.");
      System.out.println(Base64Codec.BASE64.decodeToString(split[0]));
      System.out.println(Base64Codec.BASE64.decodeToString(split[1]));
      //无法解密
      System.out.println(Base64Codec.BASE64.decodeToString(split[2]));

我们刚才已经创建了token ,在web应用中这个操作是由服务端进行然后发给客户端,客户端在下次向服务端发送
请求时需要携带这个token(这就好像是拿着一张门票一样),那服务端接到这个token 应该解析出token中的信息
(例如用户id),根据这些信息查询数据库返回相应的结果。

@Test
public void testParseToken(){
   //token
   String token =
"eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI4ODgiLCJzdWIiOiJSb3NlIiwiaWF0IjoxNTc4ODE0MjUyfQ" +
         ".-FYFMHyfTcGzq900f_Drfdsges0ge2UjaWvPW9gCDto";
   //解析token获取负载中的声明对象
   Claims claims = Jwts.parser()
         .setSigningKey("xxxx")
         .parseClaimsJws(token)
         .getBody();
   //打印声明的属性
   System.out.println("id:"+claims.getId());
   System.out.println("subject:"+claims.getSubject());
   System.out.println("issuedAt:"+claims.getIssuedAt());
}
posted @ 2021-06-20 00:39  天才淇露洛  阅读(432)  评论(0)    收藏  举报