当前位置:  开发笔记 > 后端 > 正文

Spring-boot JWT注销

如何解决《Spring-bootJWT注销》经验,为你挑选了1个好方法。

我使用这个代码https://github.com/gdongus/spring-boot-oauth-jwt-example,一切都很完美,但我不知道如何实现注销功能.有人可以给我建议吗?谢谢.



1> Kevin Peters..:

客户端注销很简单,只需丢弃您拥有的令牌即可.要提供服务器端注销功能,您的应用程序必须知道当前经过身份验证的客户端,换句话说,现有令牌.基于令牌的身份验证的"内置"问题是,如果令牌已发布,则它有效,直到它过期并且没有"远程失效"解决方案.您唯一的机会是避免使用您不信任的令牌访问请求.

因此,您必须记住名为令牌存储的容器中的每个已发布令牌.

有一些TokenStore接口的实现可以在内存中工作,也可以与数据库(JdbcTokenStore)一起工作.举一个简单的例子InMemoryTokenStore就足够了.

要使用它,必须按如下方式创建和配置令牌存储.

将此添加到您的AuthorizationServerConfiguration:

@Bean
public InMemoryTokenStore tokenStore() {
    return new InMemoryTokenStore();
}

并使用它AuthorizationServerEndpointsConfigurer:

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

将它添加到您的ResourceServerConfiguration:

@Autowired
private InMemoryTokenStore inMemoryTokenStore;
...
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
    resources.resourceId("resource").tokenStore(inMemoryTokenStore);
}

这几乎都是.现在,您可以实现您需要的注销功能,可能需要一个特殊的端点,您只需获取令牌并将其从令牌存储中删除:

inMemoryTokenStore.removeAccessToken(accessToken);
inMemoryTokenStore.removeRefreshToken(refreshToken);

请注意也删除刷新令牌,否则(如果仅删除访问令牌)客户端可以使用刷新令牌获取新的令牌.

根据您的测试,这是一个测试用例,以验证它是否正常工作:

@Test
public void getUserWithValidAuth() throws Exception {
    final HttpHeaders headers = getHttpHeader(CLIENT_USER, CLIENT_SECRET);
    final HttpEntity request = new HttpEntity<>(headers);

    final String tokenUrl = getOAuthTokenUrl(OAUTH_TOKEN_USERNAME, OAUTH_TOKEN_PASSWORD);
    final ResponseEntity response = restTemplate.exchange(tokenUrl, HttpMethod.POST, request, Object.class);
    assertTrue("Did not get auth tokens!", response.getStatusCode().is2xxSuccessful());

    final Map result = (Map) response.getBody();
    final String accessTokenAsString = (String) result.get(ACCESS_TOKEN);
    final String refreshTokenAsString = (String) result.get(REFRESH_TOKEN);

    final String resourceUrlWithToken = "http://localhost:" + port + "/users?access_token=" + accessTokenAsString;

    final ResponseEntity userResponse = restTemplate.exchange(resourceUrlWithToken, HttpMethod.GET, null,
            String.class);
    assertTrue("Could not request user data!", userResponse.getStatusCode().is2xxSuccessful());

    final OAuth2AccessToken accessToken = inMemoryTokenStore.readAccessToken(accessTokenAsString);
    final OAuth2RefreshToken refreshToken = inMemoryTokenStore.readRefreshToken(refreshTokenAsString);
    inMemoryTokenStore.removeAccessToken(accessToken);
    inMemoryTokenStore.removeRefreshToken(refreshToken);

    try {
        restTemplate.exchange(resourceUrlWithToken, HttpMethod.GET, null, String.class);
        fail("Should not get here, expected 401 for request with access token!");
    } catch (HttpClientErrorException e) {
        // would not be needed with MockMvc
    }

    final String refreshTokenUrl = REFRESH_TOKEN_URL + refreshTokenAsString;
    try {
        restTemplate.exchange(refreshTokenUrl, HttpMethod.POST, request, Object.class);
        fail("Should not get here, expected 401 for request with refresh token!");
    } catch (HttpClientErrorException e) {
        // would not be needed with MockMvc
    }
}


至少只是一个建议,使用MockMvc是一个很棒的测试框架,可以很容易地测试休息调用,你可以在使用RestTemplate时摆脱障碍和样板代码.也许你想尝试一下.

推荐阅读
k78283381
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有