当前位置:  开发笔记 > 编程语言 > 正文

如何使Spring Security OAuth2真正无状态/摆脱"状态"参数?

如何解决《如何使SpringSecurityOAuth2真正无状态/摆脱"状态"参数?》经验,为你挑选了0个好方法。

我目前正在开展一个项目,我们希望用户通过Facebook和其他OAuth2提供商登录.此外,REST api应该是无状态的.因此,不应创建/使用cookie/jsessionids.对于api的授权,在通过Facebook成功登录后,api会发布JWT.消耗其余api的webapp是使用AgularJS和satellizer构建的.我将代码缩减为github上的最小示例.

工作流程理念:

    用户进入该网站,选择"使用Facebook登录"

    Web应用程序打开一个弹出窗口,显示Facebook登录页面

    用户登录,接受和Facebook重定向到webapp

    webapp从Facebook接收令牌并使用它登录到其余的api(GET/login/facebook?code = XXXXXXXXXXXXXXXXX)

    其余的api返回JWT.

    webapp使用JWT来针对任何进一步的请求对其余api进行授权.

到目前为止工作

webapp可以处理步骤1到4

如果您使用从执行GET的OAuth2ClientContextFilter获取的重定向到没有代码参数的"/ login/facebook",其余的api可以处理步骤5和6.(此重定向发送到Facebook,您登录后,您将再次重定向到api.)

其余的api是无状态的,没有创建/需要jsessionid/cookies(禁​​用csrf并使用SessionCreationPolicy.STATELESS).除了 "登录/ facebook"调用,这个仍然创建一个jsessionid.

问题

webapp和其他api的"login/facebook?code = XXX"调用的组合不起作用.我发现当你进行GET"login/facebook"时,你将被重定向到facebook,并在网址上附加一个额外的状态参数.此外,当facebook重定向回api时,还会添加此状态参数.从我在网上找到的,这似乎是一种CSRF保护,对吧?我猜这个东西也创造了jsessionid cookie?

问题

    以上工作流程是否合理?

    我的用例中是否需要此CSRF保护?

    我怎么能禁用这种行为?我的意思是,我使用了SessionCreationPolicy.STATELESS,但Spring仍然使用jsessionid创建了一个会话.那我怎样才能创建一个真正的无状态休息api呢?(至少关于饼干...)

    这是正确的方法吗?或者我错过了什么?

示例代码

如前所述,我在GitHub上放了一个完整的最小例子.在这里,我将只发布WebSecurityConfigurerAdapter(希望)最重要的部分.该完整的文件在这里.

@EnableOAuth2Client
@Configuration
public class OAuth2ClientConfigurer extends WebSecurityConfigurerAdapter {

@Autowired
private OAuth2ClientContext oAuth2ClientContext;

@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
    httpSecurity
            .csrf().disable()
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).enableSessionUrlRewriting(false).and()
            .antMatcher("/**").authorizeRequests()
            .antMatchers("/login/**").permitAll()
            .anyRequest().authenticated().and()
            .exceptionHandling().authenticationEntryPoint(new Http403ForbiddenEntryPoint()).and()
            .addFilterBefore(statelessJwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
            .addFilterBefore(createSsoFilter(facebook(), facebookSuccessHandler(), "/login/facebook"), BasicAuthenticationFilter.class);
}

private OAuth2ClientAuthenticationProcessingFilter createSsoFilter(ClientResourceDetails clientDetails, AuthenticationSuccessHandler successHandler, String path) {
    OAuth2ClientAuthenticationProcessingFilter ssoFilter = new OAuth2ClientAuthenticationProcessingFilter(path);
    ssoFilter.setAllowSessionCreation(false);
    OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(clientDetails.getClient(), oAuth2ClientContext);
    ssoFilter.setRestTemplate(restTemplate);
    ssoFilter.setTokenServices(new UserInfoTokenServices(clientDetails.getResource().getUserInfoUri(), clientDetails.getClient().getClientId()));
    ssoFilter.setAuthenticationSuccessHandler(successHandler);
    return ssoFilter;
}

@Bean // handles the redirect to facebook
public FilterRegistrationBean oAuth2ClientFilterRegistration(OAuth2ClientContextFilter filter) {
    FilterRegistrationBean registration = new FilterRegistrationBean();
    registration.setFilter(filter);
    registration.setOrder(-100);
    return registration;
}

非常感谢您的帮助!

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