Title

oauth2使用JWT存储token

  • 使用jwt的好处

token生成的其实就是一个UUID,和业务没有丝毫的关系,这样带来最大的问题,就是需要人工持久化处理token(像处理分布式下的sessionId一样)。但是jwt就不需要,因为自包含,所以token里有身份验证信息,不需要做后台持久化处理,前端每次请求被保护的资源时请求头里带上该token就可以实现。

  • 使用 JWT

将 TokenStore 和 JwtAccessTokenConverter Bean 被 spring 托管

    /**
     * JWT token 储存
     *
     * @return
     */
    @Bean
    public TokenStore tokenStore() {
        return new JwtTokenStore(jwtAccessTokenConverter());
    }
    /**
     * JWT token 生成处理:指定签名
     *
     * @return
     */
    @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter() {
        JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
        jwtAccessTokenConverter.setSigningKey("zl");
        return jwtAccessTokenConverter;
    }

tokenStore方法返回一个TokenStore对象的子对象JwtTokenStore,供给认证服务器取来给授权服务器端点配置器,通俗点就是让OauthAuthorizationServerConfigurerAdapter(oauth授权服务器)能注入到值。
jwtAccessTokenConverter方法是根据签名生成JwtToken,同样也需要在OauthAuthorizationServerConfigurerAdapter类里注入。

/**
 * 认证服务器
 */
@Configuration
@EnableAuthorizationServer
public class OauthAuthorizationServerConfigurerAdapter extends AuthorizationServerConfigurerAdapter {


    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private UserDetailsService userDetailsService;
    @Autowired
    private TokenStore tokenStore;
    @Autowired
    private JwtAccessTokenConverter jwtAccessTokenConverter;



    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        super.configure(security);
    }

    /**
     * 客户端配置(给谁发令牌)
     * @param clients
     * @throws Exception
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory().withClient(ConsParams.Auth.GET_CLIENT_ID)
                .secret(ConsParams.Auth.GET_SECRET)
                //有效时间 2小时
                .accessTokenValiditySeconds(ConsParams.Auth.GET_TOKEN_VALIDITY_SECONDS)
                //密码授权模式和刷新令牌
                .authorizedGrantTypes(ConsParams.Auth.GE_TAUTHORIZED_GRANT_TYPES)
                .scopes(ConsParams.Auth.GE_TSCOPES);
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints
                .tokenStore(tokenStore)
                .authenticationManager(authenticationManager)
                .userDetailsService(userDetailsService)
                .accessTokenConverter(jwtAccessTokenConverter);
        }
    }
}

endpoints添加了accessTokenConverter属性,它规定了token生成器是jwtAccessTokenConverter,并按照我们设置的签名来生成。

发送请求获取 token

获取资源

  • JWT 进行扩展

新建扩展类 JwtTokenEnhancer 继承 TokenEnhancer

/**
 * Jwt token 扩展
 */
public class JwtTokenEnhancer implements TokenEnhancer {
    @Override
    public OAuth2AccessToken enhance(OAuth2AccessToken oAuth2AccessToken, OAuth2Authentication oAuth2Authentication) {

        Map<String,Object> info = new HashMap<>();
        // 添加到 token 字符串里面的数据
        info.put("show","zhang");
        //设置附加信息
        ((DefaultOAuth2AccessToken)oAuth2AccessToken).setAdditionalInformation(info);
        return oAuth2AccessToken;
    }
}

将 JwtTokenEnhancer 类被 spring 托管

@Bean
public TokenEnhancer jwtTokenEnhancer(){
      return new JwtTokenEnhancer();
}

修改 OauthAuthorizationServerConfigurerAdapter oauth认证服务器配置类

@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
    endpoints
            .tokenStore(tokenStore)
            .authenticationManager(authenticationManager)
            .userDetailsService(userDetailsService);
    // token增强器链对象
    TokenEnhancerChain enhancerChain = new TokenEnhancerChain();
        List<TokenEnhancer> enhancerList = new ArrayList<>();
        enhancerList.add(jwtTokenEnhancer);
        enhancerList.add(jwtAccessTokenConverter);
        enhancerChain.setTokenEnhancers(enhancerList);


        endpoints
                .tokenEnhancer(enhancerChain)
                .accessTokenConverter(jwtAccessTokenConverter);
}

现在就可以把数据添加到token里面了

  • 解析 JWT

导包

<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt -->
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>

写个解析接口

    @GetMapping("/userInfo")
    public ServerResponse getCurrentUser(Authentication user, HttpServletRequest request) throws UnsupportedEncodingException {

        String s = user.getPrincipal().toString();
        String name = user.getName();
        String header = request.getHeader("Authorization");
        String token = StringUtils.substringAfter(header,"bearer ");
        Claims body = Jwts.parser().setSigningKey(ConsParams.Auth.GET_SIGNING_KEY.getBytes("UTF-8"))
                .parseClaimsJws(token).getBody();

        String username = (String) body.get("username");
        log.info("解析token获取到的username为{}",username);
        log.info("从Authentication里获取到的username为{}",s);
        log.info("从Authentication里获取到的username为{}",name);
        return ServerResponse.createBySuccess(user);
    }


原文章连接:https://www.jianshu.com/p/766cf742e3e8

posted @ 2021-12-14 11:09  快乐小洋人  阅读(890)  评论(0编辑  收藏  举报