每个请求的Spring安全性,标头中包含自定义AUTH令牌

时间:2016-01-06 17:34:48

标签: java spring-mvc spring-security

我在我的应用中使用spring security。在那我必须使用自定义令牌(存储在与用户映射的数据库中)来保护REST API。

这是我的网络安全配置。

@Autowired
public DataSource dataSource;

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    auth
    .jdbcAuthentication()
    .dataSource(dataSource)
    .passwordEncoder(passwordEncoder())
    .usersByUsernameQuery(getUserQuery()).authoritiesByUsernameQuery(getAuthoritiesQuery());
}

以上代码是我的全局身份验证配置。

@Configuration
protected static class SecurityConfiguration extends WebSecurityConfigurerAdapter {

@Autowired
private UserRoleManager userRolePage;

    @Override
    protected void configure(HttpSecurity http) throws Exception 
    {
        List<RolePageMap> rolePageMaps = userRolePage.getRolePageMapList();

        for (RolePageMap rolePageMap : rolePageMaps) {
            http.authorizeRequests()
                    .antMatchers(rolePageMap.getAccessablePages().getPageValue())
                    .access("hasRole('" + rolePageMap.getUserRole().getRoleName() + "')");
        }

        http.authorizeRequests().and().formLogin()
                .usernameParameter("username").passwordParameter("password")
                .and().logout().logoutSuccessUrl("/")
                .and().exceptionHandling().accessDeniedPage("/successMessage.html")
                .and().csrf().csrfTokenRepository(csrfTokenRepository()).and()
                .addFilterAfter(csrfHeaderFilter(), CsrfFilter.class)
                .addFilterBefore(customAuthFilter(), UsernamePasswordAuthenticationFilter.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());
                final String customToken = request.getHeader(AUTH_HEADER_NAME);
                if (csrf != null && customToken == 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 Filter customAuthFilter() {
        return new OncePerRequestFilter() {
            @Override
            protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
                    FilterChain filterChain) throws ServletException, IOException {
                final String token = request.getHeader(AUTH_HEADER_NAME);
                if(token != null) {
                    UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken("admin", "admin");
                    SecurityContextHolder.getContext().setAuthentication(authToken);
                }
                filterChain.doFilter(request, response);
            }
        };
    }

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

}

注意:在上面的代码中,我在同一安全配置中使用了两个过滤器。

该配置的意图是,如果自定义令牌存在于头文件中,我们应该使用相应的过滤器,如果请求中没有,那么它应该验证CSRF令牌。

这里的问题是如果自定义存在,那么它是有效的,当我删除标题并再次调用API时,它会返回结果但不应该。

这是实现此安全性的正确方法吗?

有人可以帮我吗?

0 个答案:

没有答案