Spring-boot + Oauth2:CSRF~ Restful API

时间:2016-01-05 04:17:58

标签: java spring spring-boot csrf-protection oauth2

我正在学习Spring-boot和Oauth2。我有一些问题。

我正在实施针对CSRF的保护

.csrf()
                .requireCsrfProtectionMatcher(new AndRequestMatcher(
                    new NegatedRequestMatcher(new AntPathRequestMatcher("/test", HttpMethod.OPTIONS.toString()))
                ));

这工作正常,但当我尝试访问我的API上的另一条路径时,我收到此消息。

"error": "access_denied"
"error_description": "Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'."

我尝试在我的请求中使用JSESSIONID设置cookie但是没有工作

Status
403 Prohibido Show explanation Loading time: 22
Request headers 
Accept: application/json
Origin: chrome-extension://hgmloofddffdnphfgcellkdfbfbjeloo
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36
Authorization: Bearer 4abe8cbc-a528-4d52-8e20-a0aa198056d2
Content-Type: application/json 
DNT: 1
Accept-Encoding: gzip, deflate
Accept-Language: es-ES,es;q=0.8,en;q=0.6,und;q=0.4
Cookie: JSESSIONID=3DB726CA18F6628719703891B7DCA0A2
Response headers 
Server: Apache-Coyote/1.1 
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0 
X-Frame-Options: DENY
Cache-Control: no-store 
Pragma: no-cache 
Content-Type: application/json;charset=UTF-8 
Transfer-Encoding: chunked 
Date: Tue, 05 Jan 2016 03:59:45 GMT

此外,我尝试在我的项目上设置我的CSRF过滤器,最糟糕的是,这并没有让我获得带有JSESSIONID的Cookie。字面意思什么都不做

@Configuration
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
@EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

@Autowired
CustomAuthenticationProvider customAuthenticationProvider;

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.authenticationProvider(customAuthenticationProvider);
}

@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
    return super.authenticationManagerBean();
}

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.httpBasic().and().authorizeRequests()
            .antMatchers("/test").permitAll().anyRequest()
            .authenticated()
            .and().csrf()
            .csrfTokenRepository(csrfTokenRepository()).and()
            .addFilterAfter(csrfHeaderFilter(), CsrfFilter.class);
}

private Filter csrfHeaderFilter() {
    return new OncePerRequestFilter() {
        @Override
        protected void doFilterInternal(
                HttpServletRequest request,
                HttpServletResponse response,
                FilterChain filterChain)
                throws ServletException, IOException {
            CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
            if (csrf != null) {
                Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
                String token = csrf.getToken();
                if (cookie == null || token != null
                        && !token.equals(cookie.getValue())) {
                    cookie = new Cookie("XSRF-TOKEN", token);
                    cookie.setPath("/");
                    response.addCookie(cookie);
                }
            }
            filterChain.doFilter(request, response);
        }
    };
}

private CsrfTokenRepository csrfTokenRepository() {
    HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
    repository.setHeaderName("X-XSRF-TOKEN");
    return repository;
}
}

知道我做错了吗?

编辑我认为我找到了部分解决方案,但现在我有几个问题。

解决方案: 使我的CrsfTokenRepository成为@Bean

@Bean
public CsrfTokenRepository csrfTokenRepository() {
    HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
    repository.setHeaderName("X-XSRF-TOKEN");
    return repository;
}

仅为我的CsrfHeaderFilter

制作了全班
public class CsrfHeaderFilter extends OncePerRequestFilter {

@Override
protected void doFilterInternal(HttpServletRequest request,
        HttpServletResponse response, FilterChain filterChain)
        throws ServletException, IOException {
    CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class
            .getName());
    if (csrf != null) {
        Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
        String token = csrf.getToken();
        if (cookie == null || token != null && !token.equals(cookie.getValue())) {
            cookie = new Cookie("XSRF-TOKEN", token);
            cookie.setPath("/");
            response.addCookie(cookie);
        }
    }
    filterChain.doFilter(request, response);
}

}

并将WebSecurityConfiguration中的配置移至我的Oauth2Configuration

@Configuration
@EnableResourceServer
protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {

    @Autowired
    private CustomLogoutSuccessHandler customLogoutSuccessHandler;

    @Autowired
    private CsrfTokenRepository csrfTokenRepository;

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) {
        resources
                .resourceId(RESOURCE_ID);
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
                // Logout
                .logout()
                .logoutUrl("/oauth/logout")
                .logoutSuccessHandler(customLogoutSuccessHandler)
                .and()
                //Session management
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                //URI's to verify
                .authorizeRequests()
                .antMatchers("/test").hasRole("ADMIN")
                .antMatchers("/users").authenticated()
                .antMatchers("/**").authenticated()
                .antMatchers("/productos").hasAnyRole("ADMIN, VENDEDOR")
                .and()
                .addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class)
                .csrf()
                .csrfTokenRepository(csrfTokenRepository);
    }
}

我的问题是:

  • 这个解决方案很好吗?是一个很好的做法?
  • JSESSIONID和XSRF-Token不需要附加在我的angularjs请求中吗?

0 个答案:

没有答案