SpringBoot+SpringSecurity+SpringCloudOauth2密码模式使用(三)整合JWT格式的Token

Jwt介绍

Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。

JWT的构成

  • 第一部分我们称它为头部(header),通过base64加密
  • 第二部分我们称其为载荷(payload,类似于飞机上承载的物品),通过base64加密
  • 第三部分是签证(signature)

header

token的类型(“JWT”)和算法名称(比如:HMAC SHA256或者RSA等等)。例如:

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

payload

  • Payload JWT的第二部分是payload,它包含声明(要求)。
  • 声明是关于实体(通常是用户)和其他数据的声明。声明有三种类型: registered, public 和 private。
  • Registered claims :这里有一组预定义的声明,它们不是强制的,但是推荐。比如:iss (issuer), exp (expiration time), sub (subject), aud (audience)等。
  • Public claims : 可以随意定义。 Private claims :用于在同意使用它们的各方之间共享信息,并且不是注册的或公开的声明。 下面是一个例子
{
    "sub": '1234567890',
    "name": 'john',
    "admin":true
}

注意,不要在JWT的payload或header中放置敏感信息,除非它们是加密的。

signature

Header 和 Payload 编码后的字符串拼接后再用HS256签名算法(Header中alg指明的算法)加密,在加密的过程中还需加上secret(密钥),最后得到签名

如何生成JWT密钥

jwt官网上有相关的依赖,也可以通过在官网上验证密钥的信息,相关依赖如下

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.0</version>
</dependency>
/**
 * 生成Jwt
 */
@Test
public void testJwt() {
    long date = System.currentTimeMillis() + 60 * 1000;// 当前时间(毫秒)增加60秒
    Date date1=new Date(date); // 获得时间
    String rose = Jwts.builder()
            .setId("888") // 设置JWTId
            .setSubject("Rose") // 设置标题
            .setExpiration(date1)// 设置当前token过期时间
            .setIssuedAt(new Date())// 设置当前token创建时间
            .claim("name","jack") // 自定义参数设置
            .claim("logo","img.jpg")// 自定义参数设置
            .signWith(SignatureAlgorithm.HS256, "112233").compact();// 设置密钥和密钥的加密方式
    System.out.println("rose = " + rose);
}
/**
* 解析token,解析token时需要之前设置的singKey密钥才能进行解析
*/
@Test
public  void ParseToken(){
        String token="eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI4ODgiLCJzdWIiOiJSb3NlIiwiZXhwIjoxNjIyNTM4MDY5LCJpYXQiOjE2MjI1MzgwMDksIm5hbWUiOiJqYWNrIiwibG9nbyI6ImltZy5qcGcifQ.VAzLBSShT1kxET67QCrxdrwqQ5Eyz42mBsY4Vb1HuCY";
        Claims claims = (Claims) Jwts.parser().setSigningKey("112233").parse(token).getBody();
        String id = claims.getId();
        System.out.println("id = " + id);
        String subject = claims.getSubject();
        System.out.println("subject = " + subject);
        Date issuedAt = claims.getIssuedAt();
        System.out.println("issuedAt = " + issuedAt);
    }

相关的JWT工具类可以查看JAVA——JWT帮助类

在密码模式中整合JWT使用

本篇文章使用到了上一章的代码SpringBoot+SpringSecurity+SpringCloudOauth2密码模式使用(二),可以参考上一章是如何实现密码模式的,创建一个MyJwtTokenStore配置类

@Configuration
public class MyJwtTokenStore {
    /**
     * 储存token的Store
     * @return
     */
    @Bean
    public TokenStore jwtTokenStore(){
        return new JwtTokenStore(jwtAccessTokenConverter());
    }

    /**
     * 这个bean将自动生成的token字符转为jwt格式的token
     * @return
     */
    @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter(){
        JwtAccessTokenConverter jwtAccessTokenConverter=new JwtAccessTokenConverter();
        // 设置当前Jwt的密钥
        jwtAccessTokenConverter.setSigningKey("test_key");
        return jwtAccessTokenConverter;
    }
}

在授权服务器里加入之前注入好前Bean

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

    @Lazy
    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private AuthenticationManager authenticationManager;
    @Lazy
    @Autowired
    private JwtAccessTokenConverter jwtAccessTokenConverter;

    @Lazy
    @Autowired
    private UserService userService;

    @Lazy
    @Autowired
    private TokenStore jwtTokenStore;


    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        // 设置相关
        endpoints.authenticationManager(authenticationManager)
                .userDetailsService(userService)
                .tokenStore(jwtTokenStore)// 储存Token的Store
                .accessTokenConverter(jwtAccessTokenConverter)// 将token转为Jwt格式
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                // 授权服务的名字
                .withClient("clients")
                // 授权码
                .secret(passwordEncoder.encode("112233"))
                // 重定向位置
                .redirectUris("http://www.baidu.com")
                // 授权范围
                .scopes("all")
                /**
                 * authorization_code 授权码模式
                 * password 密码模式
                 *
                 */
                .authorizedGrantTypes("authorization_code","password");
    }
}

启动项目

这里也是使用postMan进行测试,观察以下获取到的·access_token字符串,将他拿到jwt官网上进行测试观察

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJhZG1pbiIsInNjb3BlIjpbImFsbCJdLCJleHAiOjE2MjMyMjc0ODQsInN5cyI6InpwaiIsImF1dGhvcml0aWVzIjpbImFkbWluIl0sImp0aSI6IjFmOWRmYzkxLWExZmUtNGRmZi05Zjk2LTY5Y2QwODFlOGQ2YiIsImNsaWVudF9pZCI6ImNsaWVudHMifQ.ZMfbt3kvn1A2wdHIbRyGlnE_f9I_cDh1RytxY9Ce_sA

在这里插入图片描述

从官网的对比来看是没有问题的,接下来就可以通过对比当前token是否有效来判断有没有访问当前资源的权利了

在这里插入图片描述

通过判断请求头上是否带有token并且token正确

@RestController
@RequestMapping("/user")
public class UserController {

    @GetMapping("/getCurrentUser")
    public Object getCurrentUser(Authentication authentication, HttpServletRequest request){
        String header = request.getHeader("Authorization");
        String token = header.substring(header.lastIndexOf("bearer") + 7);
        return Jwts.parser().setSigningKey("test_key".getBytes(StandardCharsets.UTF_8))
                .parse(token).getBody();

    }
}

bearer后面必须要有空格,博主使用的是正规一点的token设置方式,可以不用和我一样,如果一样就打一个空格,这样就可以获取到相关的资源了

在这里插入图片描述

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

麦片王子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值