Reputation: 383
My login page.
<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>
But if I didn't disable the csrf
,it alway be accessDenied
.I don't know where is the problem.
My config code below.
@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!
}
}
And does anyone knows how to ues thymeleaf
in ng-route
's partial page.Just see this question.
Upvotes: 0
Views: 3942
Reputation: 2070
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
Particularly, the relevant section is:
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.
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.
Upvotes: 2
Reputation: 2424
You should include an input hidden to send the CSRF token in the POST method when the user submit the form.
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
You already included a input hidden _csrf in your template, but the value is wrong, just change it.
You can read more about CSRF here:
https://docs.spring.io/spring-security/site/docs/current/reference/html/csrf.html
Upvotes: 2