当前位置: 首页 > 知识库问答 >
问题:

Spring security JWT刷新令牌未过期

杨凯旋
2023-03-14
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Value("${security.signing-key}")
private String signingKey;

@Value("${security.encoding-strength}")
private Integer encodingStrength;

@Value("${security.security-realm}")
private String securityRealm;

@Autowired
private UserDetailsService userDetailsService;

@Bean
@Override
protected AuthenticationManager authenticationManager() throws Exception {
    return super.authenticationManager();
}

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}

@Bean
public PasswordEncoder passwordEncoder() {
    PasswordEncoder encoder = new BCryptPasswordEncoder();
    return encoder;
}

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().httpBasic()
            .realmName(securityRealm).and().csrf().disable();

}

@Bean
public JwtAccessTokenConverter accessTokenConverter() {
    JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
    converter.setSigningKey(signingKey);
    return converter;
}

@Bean
public TokenStore tokenStore() {
    return new JwtTokenStore(accessTokenConverter());
}

@Bean
@Primary
public DefaultTokenServices tokenServices() {
    DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
    defaultTokenServices.setTokenStore(tokenStore());
    defaultTokenServices.setSupportRefreshToken(true);
    defaultTokenServices.setRefreshTokenValiditySeconds(10);
    return defaultTokenServices;
}

}

共有1个答案

裴良弼
2023-03-14

我确实找到了答案,只是忘了更新我的票。因此,默认情况下JwtTokenStore不支持刷新令牌。以下是JwtTokenStore源代码。所以这意味着,在设置中启用令牌实际上不会使其工作。我所做的是创建自己的JWT令牌存储,扩展JwtTokenStore,并编写自己的刷新令牌逻辑。

public class MyJwtTokenStore extends JwtTokenStore {

@Autowired
UserRepository userRepository;

public MyJwtTokenStore(JwtAccessTokenConverter jwtTokenEnhancer) {
    super(jwtTokenEnhancer);
}

@Override
public void storeRefreshToken(OAuth2RefreshToken refreshToken, OAuth2Authentication authentication) {
    String username = authentication.getUserAuthentication().getName();
    User user = userRepository.findByEmail(username);
    user.setToken(refreshToken.getValue());
    userRepository.save(user);
}

@Override
public OAuth2RefreshToken readRefreshToken(String token) {
    OAuth2Authentication authentication = super.readAuthentication(token);
    String username = authentication.getUserAuthentication().getName();
    User user = userRepository.findByEmail(username);
    if (!token.equals(user.getToken())) {
        return null;
    }
    OAuth2RefreshToken refreshToken = new DefaultOAuth2RefreshToken(token);
    return refreshToken;
}

@Override
public void removeRefreshToken(OAuth2RefreshToken token) {
    OAuth2Authentication authentication = super.readAuthentication(token.getValue());
    String username = authentication.getUserAuthentication().getName();
    User user = userRepository.findByEmail(username);
    user.setToken(null);
    userRepository.save(user);
}

}

在这之后,我刚刚更新了我的TokenStore Bean

@Bean
public TokenStore tokenStore() {
    MyJwtTokenStore jwtTokenStore = new MyJwtTokenStore(accessTokenConverter());
    return jwtTokenStore;
    // return new JwtTokenStore(accessTokenConverter());
}

最后,我将剩余的设置添加到AuthorizationServerConfigurerAdapter类中,以支持刷新令牌并赋予它有效时间。

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Value("${security.jwt.client-id}")
private String clientId;

@Value("${security.jwt.client-secret}")
private String clientSecret;

@Value("${security.jwt.grant-type}")
private String grantType;

@Value("${security.jwt.grant-type-other}")
private String grantTypeRefresh;

@Value("${security.jwt.scope-read}")
private String scopeRead;

@Value("${security.jwt.scope-write}")
private String scopeWrite = "write";

@Value("${security.jwt.resource-ids}")
private String resourceIds;

@Autowired
private TokenStore tokenStore;

@Autowired
private JwtAccessTokenConverter accessTokenConverter;

@Autowired
private AuthenticationManager authenticationManager;

@Autowired
private AppUserDetailsService userDetailsService;

@Autowired
private PasswordEncoder passwordEncoder;


@Override
public void configure(ClientDetailsServiceConfigurer configurer) throws Exception {
    configurer.inMemory()
            .withClient(clientId)
            .secret(passwordEncoder.encode(clientSecret))
            .authorizedGrantTypes(grantType, grantTypeRefresh).scopes(scopeRead, scopeWrite)
            .resourceIds(resourceIds).autoApprove(false).accessTokenValiditySeconds(1800) // 30min
            .refreshTokenValiditySeconds(86400); //24 hours
}

@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
    TokenEnhancerChain enhancerChain = new TokenEnhancerChain();
    enhancerChain.setTokenEnhancers(Arrays.asList(accessTokenConverter));
    endpoints.tokenStore(tokenStore).accessTokenConverter(accessTokenConverter).tokenEnhancer(enhancerChain)
            .reuseRefreshTokens(false).authenticationManager(authenticationManager)
            .userDetailsService(userDetailsService);
}

@Bean
public FilterRegistrationBean corsFilter() {
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    CorsConfiguration config = new CorsConfiguration();
    config.setAllowCredentials(true);
    config.addAllowedOrigin("*"); // http://localhost:4200
    config.addAllowedHeader("*");
    config.addAllowedMethod("*");
    source.registerCorsConfiguration("/**", config);
    FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
    bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
    return bean;
}
 类似资料:
  • 我想从谷歌得到访问令牌。Google API表示,要获得访问令牌,将代码和其他参数发送到令牌生成页面,响应将是一个JSON对象,如下所示: 但是,我没有收到刷新令牌。我的答复是:

  • 我正在编写一个应用程序,调用来自Flutter的google fit rest api。 我需要使用(https://pub.dev/packages/google_sign_in)与谷歌签名。我可以毫无问题地获得一个令牌(见是否有人设法从谷歌登录(Flutter)获得id令牌),但如何获得一个新的令牌时,它是过期的? 我不想要求用户每小时登录并获得一个新的令牌

  • 授权服务器可以给Web应用客户端和本机应用程序客户端颁发刷新令牌。 刷新令牌在传输和储存时必须保持机密性,并只与授权服务器和刷新令牌被颁发的客户端共享。授权服务器必须维护刷新令牌和它被颁发给的客户端之间的绑定。刷新令牌必须只能使用带有RFC2818定义的服务器身份验证的1.6所述的TLS 传输。 授权服务器必须验证刷新令牌和客户端身份之间的绑定,无论客户端身份是否能被验证。当无法进行客户端身份验证

  • 刷新令牌是用于获取访问令牌的凭据。刷新令牌由授权服务器颁发给客户端,用于在当前访问令牌失效或过期时,获取一个新的访问令牌,或者获得相等或更窄范围的额外的访问令牌(访问令牌可能具有比资源所有者所授权的更短的生命周期和更少的权限)。颁发刷新令牌是可选的,由授权服务器决定。如果授权服务器颁发刷新令牌,在颁发访问令牌时它被包含在内(即图1中的步骤D)。 刷新令牌是一个代表由资源所有者给客户端许可的授权的字

  • 我对oauth2中的刷新令牌有点困惑。如它所说的访问令牌限制了黑客可以使用用户凭证的1小时的时间窗口,刷新令牌是万岁令牌,可以用来重新创建访问令牌。 我很困惑,如果有人从cookie中窃取了访问令牌,他也可以窃取刷新令牌,并可以使用刷新令牌创建新的访问令牌,因为我在JQuery中有ajax请求(客户端)

  • google oauth2刷新令牌何时过期? 我所说的过期是指过期是因为经过了某个时间跨度(不是因为用户已撤销访问权限或用户已请求新的刷新令牌) 我做了一些研究,没有一个引用官方的谷歌文档(我也找不到一个有效的谷歌文档) 其他一些问题表示,由于时间,它从未过期: 谷歌刷新令牌过期了吗? https://community.fitbit.com/t5/web-api-development/inva