【问题标题】:how could I use csrf in spring security我如何在 Spring Security 中使用 csrf
【发布时间】:2016-08-13 05:36:05
【问题描述】:

我的登录页面。

<form class="form-horizontal" ng-controller="loginCtrl" action="/login" method="post">
    <div class="form-group input-login">
        <div ng-if="message.error" class="alert alert-danger">
            <p>Invalid username and password.</p>
        </div>
        <div ng-if="message.logout" class="alert alert-success">
            <p>You have been logged out successfully.</p>
        </div>
        <label  class="control-label sr-only">Email</label>
        <div class="col-md-12">
            <input type="text" class="form-control" ng-model="user.username" name="username" placeholder="NickName"/>
        </div>
    </div>
    <div class="form-group input-login">
        <label  class="control-label sr-only">Password</label>
        <div class="col-md-12">
            <input type="password" class="form-control" ng-model="user.password" name="password" placeholder="Password"/>
        </div>
    </div>
    <input name="_csrf" type="hidden" value="6829b1ae-0a14-4920-aac4-5abbd7eeb9ee" /> 
    <div class="form-group sub-login">
        <div class=" col-md-12">
            <button name="submit" type="submit" class="btn btn-primary btn-login">Login</button>
        </div>
    </div>
</form>

但如果我没有禁用csrf,它总是accessDenied。我不知道问题出在哪里。

下面是我的配置代码。

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDao userDao;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        auth.userDetailsService(new UserService(userDao)).passwordEncoder(new MD5Util());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.authorizeRequests()
                .antMatchers("/", "/index").access("hasRole('USER')")
                .and()
                    .formLogin()
                    .loginPage("/login")
                    .failureUrl("/login#/signin?error=1")
                    .successHandler(new LoginSuccessHandler())
                    .usernameParameter("username").passwordParameter("password")
                .and()
                    .logout()
                    .logoutUrl("/logout")
                    .logoutSuccessUrl("/login#/signin?logout=1")
                .and()
                    .exceptionHandling().accessDeniedPage("/Access_Denied")
                .and().csrf().disable(); // If I  disable this csrf,it worked!

    }
}

有谁知道如何在ng-route 的部分页面中使用thymeleaf。看看这个question

【问题讨论】:

标签: spring spring-mvc spring-security


【解决方案1】:

您最好查看此链接:https://spring.io/blog/2015/01/12/the-login-page-angular-js-and-spring-security-part-ii

具体来说,相关部分是:

CSRF 保护

这很好,因为这意味着 Spring Security 的内置 CSRF 保护已经启动,以防止我们自取其辱。它所需要的只是在名为“X-CSRF”的标头中发送给它的令牌。 CSRF 令牌的值在加载主页的初始请求的 HttpRequest 属性中的服务器端可用。要将其发送到客户端,我们可以使用服务器上的动态 HTML 页面呈现它,或者通过自定义端点公开它,或者我们可以将它作为 cookie 发送。最后一个选择是最好的,因为 Angular 已经内置了对基于 cookie 的 CSRF(它称为“XSRF”)的支持。

所以我们在服务器上只需要一个自定义过滤器来发送 cookie。 Angular 希望 cookie 名称为“XSRF-TOKEN”,而 Spring Security 将其作为请求属性提供,因此我们只需要将值从请求属性传递到 cookie:

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);
    }
}

经过一番努力,最后一句话是:

有了这些更改,我们不需要在客户端做任何事情,登录表单现在可以工作了。

【讨论】:

    【解决方案2】:

    当用户提交表单时,您应该在 POST 方法中包含一个隐藏的输入以发送 CSRF 令牌。

    <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
    

    您已经在模板中包含了一个输入 hidden _csrf,但是值错误,只需更改它。

    您可以在此处阅读有关 CSRF 的更多信息:

    https://docs.spring.io/spring-security/site/docs/current/reference/html/csrf.html

    【讨论】:

    • 不起作用。因为我没有使用Jsp,所以我使用Thymeleaf。但问题是Thymeleaf 不起作用。你可以看到这个question
    • 我也在使用 Thymeleaf 和 Csrf,它有效!您使用的是什么 Thymeleaf 版本?尝试使用标签
      。 spring 文档说,如果您使用此标签,则会自动包含 CsrfToken。你在混合 Thymeleaf 和 A​​ngular 吗?
    • 2.1.4。我也使用ng-route 来路由我的页面。但是在我的部分页面中,Thymeleaf 不起作用。主页很好。你能看到这个question
    猜你喜欢
    • 1970-01-01
    • 2018-07-21
    • 2021-09-11
    • 2015-12-10
    • 2016-09-01
    • 2015-03-28
    • 2015-05-10
    • 2014-10-26
    相关资源
    最近更新 更多