美文网首页
Spring Security oauth2令牌配置

Spring Security oauth2令牌配置

作者: 寂静的春天1988 | 来源:发表于2020-07-29 14:41 被阅读0次

基本的token参数配置

@Data
public class Oauth2Properties {
    
    private Oauth2ClientProperties[] clients={};
    
}
@Data
public class Oauth2ClientProperties {
    private String clientId;
    
    private String clientSecret;
    
    private int accessTokenValiditySeconds = 7200;
}
fuiou.security.oauth2-properties.clients[0].clientId=fuiou
fuiou.security.oauth2-properties.clients[0].clientSecret=fuiousecret
fuiou.security.oauth2-properties.clients[0].accessTokenValiditySeconds=7200
@Configuration
@EnableAuthorizationServer
public class FuiouAuthorizationServerConfig extends AuthorizationServerConfigurerAdapter{
    
    @Autowired
    private AuthenticationManager authenticationManager;
    
    @Autowired
    private UserDetailsService userDetailsService;
    
    @Autowired
    private SecurityProperties securityProperties;
    
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManager)
                .userDetailsService(userDetailsService);
    }
    
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        InMemoryClientDetailsServiceBuilder builder=clients.inMemory();
        if(ArrayUtils.isNotEmpty(securityProperties.getOauth2Properties().getClients())) {
            for (Oauth2ClientProperties cofnig : securityProperties.getOauth2Properties().getClients()) {
                builder.withClient(cofnig.getClientId())
                   .secret(cofnig.getClientSecret())
                   .accessTokenValiditySeconds(cofnig.getAccessTokenValiditySeconds())
                   .authorizedGrantTypes("refresh_token","password")
                   .scopes("all");
            }
        }
    }
    
}

现在的token存储在内存中,一旦服务器重启,token就失效了。

让token持久化到redis中

@Configuration
public class TokenStoreConfig {
    
    @Autowired
    private RedisConnectionFactory connectionFactory;
    
    
    @Bean
    public TokenStore redisTokenStore() {
        return new RedisTokenStore(connectionFactory);
    }
}
    @Autowired
    private TokenStore redisTokenStore;
    
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints
                .tokenStore(redisTokenStore)
                .authenticationManager(authenticationManager)
                .userDetailsService(userDetailsService);
    }

使用jwt代码默认token

jwt的特点:
1、自包含 本身是有意义的,可以根据令牌解析出user信息,而之前的token是uuid生成的是无意义的,还要根据uuid去redis或session中去拿。

2、密签 用于数据签名

3、可扩展 可以在jwt中加一些自定义的信息
注意:jwt中不能放敏感的数据,如用户密码等。

整合jwt

@Configuration
public class TokenStoreConfig {
    
    @Autowired
    private RedisConnectionFactory connectionFactory;
    
    
    
    @Bean
    @ConditionalOnProperty(prefix = "fuiou.security.oauth2-properties",name = "storeType",havingValue = "redis")
    public TokenStore redisTokenStore() {
        return new RedisTokenStore(connectionFactory);
    }
    
    @Configuration
    @ConditionalOnProperty(prefix = "fuiou.security.oauth2-properties",name = "storeType",havingValue = "jwt",matchIfMissing = true)
    public static class JwtTokenConfig{
        @Autowired
        private SecurityProperties securityProperties;
        
        @Bean
        public TokenStore jwtTokenStore() {
            return new JwtTokenStore(jwtAccessTokenConverter());
        }
        
        /**
         * 配置jwt签名
         * @return
         */
        @Bean
        public JwtAccessTokenConverter jwtAccessTokenConverter() {
            JwtAccessTokenConverter accessTokenConverter=new JwtAccessTokenConverter();
            accessTokenConverter.setSigningKey(securityProperties.getOauth2Properties().getJwtSigningKey());
            return accessTokenConverter;
        }
    }
}

注意:注入两个TokenStore可能会冲突,使用了@ConditionalOnProperty注解。matchIfMissing = true的意思是没有匹配到也生效。
@ConditionalOnProperty(prefix = "fuiou.security.oauth2-properties",name = "storeType",havingValue = "jwt",matchIfMissing = true)这行的意思是如果配置了fuiou.security.oauth2-properties.storeType的值是jwt,或者没配这个属性,都生效。

重启下一,密码模式获取token


image.png

可以看到获取的都是jwt格式的token了。

扩展

public class FuiouJwtTokenEnhancer implements TokenEnhancer{

    @Override
    public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
        Map<String,Object> info=new HashMap<String,Object>();
        info.put("company", "fuiou");
        ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(info);
        return accessToken;
    }

}
        @Bean
        @ConditionalOnMissingBean(name="jwtTokenEnhancer")
        public TokenEnhancer jwtTokenEnhancer() {
            return new FuiouJwtTokenEnhancer();
        }
@Autowired(required = false)
    private TokenEnhancer jwtTokenEnhancer;

    
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints
                .tokenStore(redisTokenStore)
                .authenticationManager(authenticationManager)
                .userDetailsService(userDetailsService);
        if(jwtAccessTokenConverter!=null && jwtTokenEnhancer!=null) {
            TokenEnhancerChain enhancerChain=new TokenEnhancerChain();
            List<TokenEnhancer> enhancers=new ArrayList<TokenEnhancer>();
            enhancers.add(jwtTokenEnhancer);
            enhancers.add(jwtAccessTokenConverter);
            enhancerChain.setTokenEnhancers(enhancers);
            endpoints
                .tokenEnhancer(enhancerChain)
                .accessTokenConverter(jwtAccessTokenConverter);
        }
    
    }
    @PostMapping("/me")
    public Object me(Authentication user){
        return user;
    }

但是访问/user/me接口发现返回的数据并没有包含额外增加的自定义数据。额外的数据需要我们自己解析。
解析jwt的pom

    <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.7.0</version>
        </dependency>

解析jwt

    @PostMapping("/me")
    public Object me(Authentication user,HttpServletRequest request) throws ExpiredJwtException, UnsupportedJwtException, MalformedJwtException, SignatureException, IllegalArgumentException, UnsupportedEncodingException{
        String header=request.getHeader("Authorization");
        String token=StringUtils.substringAfter(header, "bearer ");
        Claims claims=Jwts.parser().setSigningKey(securityProperties.getOauth2Properties().getJwtSigningKey().getBytes("utf-8"))
        .parseClaimsJws(token).getBody();
        String company=(String)claims.get("company");
        log.info("company==>"+company);
        return user;
    }

刷新token

token过期后根据refresh_token重新获取token


image.png
image.png

相关文章

网友评论

      本文标题:Spring Security oauth2令牌配置

      本文链接:https://www.haomeiwen.com/subject/diocrktx.html