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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM