我如何在Spring Security中使用CSRF [英] how could I use csrf in spring security

查看:260
本文介绍了我如何在Spring Security中使用CSRF的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的登录页面.

<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.我不知道问题出在哪里.

But if I didn't disable the csrf,it alway be accessDenied.I don't know where is the problem.

下面的我的配置代码.

@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.只需查看此

And does anyone knows how to ues thymeleaf in ng-route's partial page.Just see this question.

推荐答案

您最好的选择是查看以下链接:

Your best bet would be to have a look at this link: 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")的支持.

CSRF Protection

That’s good because it means that Spring Security’s built-in CSRF protection has kicked in to prevent us from shooting ourselves in the foot. All it wants is a token sent to it in a header called "X-CSRF". The value of the CSRF token was available server side in the HttpRequest attributes from the initial request that loaded the home page. To get it to the client we could render it using a dynamic HTML page on the server, or expose it via a custom endpoint, or else we could send it as a cookie. The last choice is the best because Angular has built in support for CSRF (which it calls "XSRF") based on cookies.

因此,我们在服务器上所需的只是一个自定义过滤器,该过滤器将发送cookie. Angular希望cookie名称为"XSRF-TOKEN",Spring Security将其作为请求属性提供,因此我们只需要将值从请求属性转移到cookie:

So all we need on the server is a custom filter that will send the cookie. Angular wants the cookie name to be "XSRF-TOKEN" and Spring Security provides it as a request attribute, so we just need to transfer the value from a request attribute to a 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);
    }
}

经过更多的工作,最后一句话是:

After a bit more work, the last sentence is:

有了这些更改,我们不需要在客户端做任何事情,并且登录表单现在可以使用了.

With those changes in place we don’t need to do anything on the client side and the login form is now working.

这篇关于我如何在Spring Security中使用CSRF的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆