我的登录页面。
<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!
}
}
有人知道如何在thymeleaf
的部分页面中使用ng-route
。请看question。
答案 0 :(得分: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);
}
}
经过多一点工作后,最后一句是:
有了这些更改,我们无需在客户端执行任何操作,登录表单现在正在运行。
答案 1 :(得分:0)
当用户提交表单时,您应该包含一个隐藏的输入以在POST方法中发送CSRF令牌。
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
您已在模板中添加了隐藏_csrf的输入,但该值错误,只需更改即可。
您可以在此处阅读有关CSRF的更多信息:
https://docs.spring.io/spring-security/site/docs/current/reference/html/csrf.html