首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用Security在OAuth2 web客户端上存储JWT令牌

使用Security在OAuth2 web客户端上存储JWT令牌
EN

Stack Overflow用户
提问于 2019-05-14 22:53:56
回答 1查看 2.4K关注 0票数 3

我正在使用SpringBoot2.1.3和SpringSecurity5.1.3实现一个OAuth2 web应用程序客户机,即通过授权代码授予类型从授权服务器获取JWT令牌,并调用受保护的资源服务器。

到目前为止,该实现是这样查找的:

用于调用受保护资源的安全配置和restTemplate bean:

代码语言:javascript
复制
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .antMatchers("/").permitAll()
            .anyRequest().authenticated()
            .and()
            .oauth2Login()
            .and()
            .oauth2Client()
            .and().logout().logoutSuccessUrl("/");
    }

    @Bean
    public RestTemplate restTemplate(OAuth2AuthorizedClientService clientService) {
        RestTemplate restTemplate = new RestTemplate();
        List<ClientHttpRequestInterceptor> interceptors = restTemplate.getInterceptors();
        if (CollectionUtils.isEmpty(interceptors)) {
            interceptors = new ArrayList<>();
        }
        interceptors.add(new AuthorizationHeaderInterceptor(clientService));
        restTemplate.setInterceptors(interceptors);
        return restTemplate;
    }
}

在InMemoryOAuth2AuthorizedClientService中添加授权头(来自框架的restTemplate)的拦截器:

代码语言:javascript
复制
public class AuthorizationHeaderInterceptor implements ClientHttpRequestInterceptor {

    private OAuth2AuthorizedClientService clientService;

    public AuthorizationHeaderInterceptor(OAuth2AuthorizedClientService clientService) {
        this.clientService = clientService;
    }

    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] bytes, ClientHttpRequestExecution execution) throws IOException {
         Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String accessToken = null;
        if (authentication != null && authentication.getClass().isAssignableFrom(OAuth2AuthenticationToken.class)) {
            OAuth2AuthenticationToken auth = (OAuth2AuthenticationToken) authentication;
            String clientRegistrationId = auth.getAuthorizedClientRegistrationId();
            OAuth2AuthorizedClient client = clientService.loadAuthorizedClient(clientRegistrationId, auth.getName());
            accessToken = client.getAccessToken().getTokenValue();
            request.getHeaders().add("Authorization", "Bearer " + accessToken);
        }
        return execution.execute(request, bytes);
    }
}

以及调用受保护资源服务器的控制器:

代码语言:javascript
复制
@Controller
@RequestMapping("/profile")
public class ProfileController {

    @Autowired
    private RestTemplate restTemplate;

    @Value("${oauth.resourceServerBase}")
    private String resourceServerBase;

    @GetMapping
    public String getProfile(Model model) {
        Profile profile = restTemplate.getForEntity(resourceServerBase + "/api/profile/", Profile.class).getBody();
        model.addAttribute("profile", profile);
        return "profile";
    }
}

OAuth2客户端配置直接位于application.yml中:

代码语言:javascript
复制
spring:
  security:
    oauth2:
      client:
        registration:
          auth-server:
            client-id: webClient
            client-secret: clientSecret
            scope: read,write
            authorization-grant-type: authorization_code
            redirect-uri: http://localhost:8081/client/login/oauth2/code/auth-server
        provider:
          auth-server:
            authorization-uri: http://localhost:8080/auth-server/oauth/authorize
            token-uri: http://localhost:8080/auth-server/oauth/token
            user-info-uri: http://localhost:8082/resource-server/users/info
            user-name-attribute: user_name

在进行了一些调试之后,我注意到在通过OAuth2LoginAuthtenticationFilter的成功身份验证流结束时,框架通过提供的InMemoryOAuth2AuthorizedClientService将获得的访问和刷新JWT令牌存储在OAuth2AuthorizedClient模型下的内存中。

我试图了解如何覆盖此行为,以便在服务器重新启动后令牌仍然可用。并根据这一点保持用户登录。

我应该只提供一个定制的OAuth2AuthorizedClientService实现吗?我如何配置Spring安全性来使用它?这个自定义实现应该将令牌存储在cookie中吗?

EN

回答 1

Stack Overflow用户

发布于 2019-05-15 01:37:10

我应该提供一个自定义的OAuth2AuthorizedClientService实现吗?

我想是的,为了解决你的用例

如何配置Security来使用它?

来自春季医生

如果您想提供AuthorizationRequestRepository的自定义实现,将OAuth2AuthorizationRequest的属性存储在Cookie中,您可以配置它,如下面的示例所示:

代码语言:javascript
复制
@EnableWebSecurity
public class OAuth2ClientSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .oauth2Client()
                .authorizationCodeGrant()
                    .authorizationRequestRepository(this.cookieAuthorizationRequestRepository())
                    ...
    }

    private AuthorizationRequestRepository<OAuth2AuthorizationRequest> cookieAuthorizationRequestRepository() {
        return new HttpCookieOAuth2AuthorizationRequestRepository();
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56139650

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档