Issue in configuring spring security 4 - spring

I googled and searched on stackoverflow but I had no success
I'm trying to setup spring security in my web app. I'm using and embedded jetty and these spring versions:
spring applicationframework 4.3.5
spring security 4.2.1
tiles 3
I wrote the following security config (a very simple one)
#Configuration
#EnableWebSecurity
public class WebSecurityCfg extends WebSecurityConfigurerAdapter
{
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception
{
auth.inMemoryAuthentication().withUser("admin").password("123456").roles("ADMIN");
}
#Override
protected void configure(HttpSecurity http) throws Exception
{
http
.authorizeRequests()
.antMatchers("/adminWebTheme/**")
.permitAll()
.antMatchers("/pages/**")
.access("hasRole('ADMIN')")
.and()
.formLogin()
.loginPage("/pages/loginPage")
.permitAll()
.usernameParameter("username")
.passwordParameter("password")
.defaultSuccessUrl("/pages/adminHome")
.failureUrl("/pages/loginPage?error=true")
.and()
.logout()
.permitAll()
.logoutSuccessUrl("/pages/loginPage?logout=true")
.and()
.csrf();
}
}
This is my security initializer
public class WebSecurityInitializer extends AbstractSecurityWebApplicationInitializer
{
}
Basically I want to use my custom login form.
This is my login JSP body:
<%# taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles"%>
<%# taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%# taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%# page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<tiles:insertDefinition name="loginPageTemplate">
<tiles:putAttribute name="head">
<title><spring:message code="comm.server.login.page.title" /></title>
</tiles:putAttribute>
<tiles:putAttribute name="body">
<div class="container">
<div class="row">
<div class="col-md-4 col-md-offset-4">
<div class="login-panel panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><spring:message code="comm.server.login.msg" /></h3>
</div>
<div class="panel-body">
<c:if test="${not empty param.error && param.error }">
<div class="alert alert-error">
<spring:message code="comm.server.login.error.msg" />
</div>
</c:if>
<c:if test="${not empty param.logout && param.logout }">
<div class="alert alert-succes">
<spring:message code="comm.server.login.logout.msg" />
</div>
</c:if>
<form role="form" method="post" action='<spring:url value="/login" />'>
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>.
<fieldset>
<div class="input-group input-sm">
<label class="input-group-addon" for="username"><i class="fa fa-user"></i></label>
<input class="form-control" placeholder='<spring:message code="comm.server.login.username.placeholder" />' name="username" id="username"
type="text" autofocus>
</div>
<div class="input-group input-sm">
<label class="input-group-addon" for="password"><i class="fa fa-lock"></i></label>
<input class="form-control" placeholder='<spring:message code="comm.server.login.password.placeholder" />'
name="password" id="password" type="password" value="">
</div>
<div class="checkbox">
<label> <input name="remember" id="remember" type="checkbox"
value='<spring:message code="comm.server.login.rememberme" />'><spring:message code="comm.server.login.rememberme" />
</label>
</div>
<!-- Change this to a button or input when using this as a form -->
<!-- Login -->
<button id="accedi" name="accedi" class="btn btn-lg btn-success btn-block"><spring:message code="comm.server.login.button" /></button>
</fieldset>
</form>
</div>
</div>
</div>
</div>
</div>
</tiles:putAttribute>
</tiles:insertDefinition>
From the previous code it seems to me all correct. I tried the access to the login page and i can access to the page successfully.
Now I have 2 kind of problem:
If i try to access to the page ..../pages/adminHome the login page is not showed
If I put username and password in my login page, the submit to the url "/login" fails because it tells me no login url is found
By the previous behaviour it's like is spring secuirty is not called at all and i can't figure the reasong
When I start my application i see the following logs:
2017-01-01 12:11:47,470 5469 [main] INFO org.apache.tiles.access.TilesAccess - Publishing TilesContext for context: org.springframework.web.servlet.view.tiles3.SpringWildcardServletTilesApplicationContext
2017-01-01 12:11:47,522 5521 [main] DEBUG o.s.s.c.a.a.c.AuthenticationConfiguration$EnableGlobalAuthenticationAutowiredConfigurer - Eagerly initializing {webSecurityCfg=it.eng.tz.comm.svr.web.config.WebSecurityCfg$$EnhancerBySpringCGLIB$$26b9578a#16a49a5d}
2017-01-01 12:11:47,679 5678 [main] DEBUG o.s.s.w.a.e.ExpressionBasedFilterInvocationSecurityMetadataSource - Adding web access control expression 'permitAll', for ExactUrl [processUrl='/pages/loginPage?error=true']
2017-01-01 12:11:47,680 5679 [main] DEBUG o.s.s.w.a.e.ExpressionBasedFilterInvocationSecurityMetadataSource - Adding web access control expression 'permitAll', for ExactUrl [processUrl='/pages/loginPage']
2017-01-01 12:11:47,681 5680 [main] DEBUG o.s.s.w.a.e.ExpressionBasedFilterInvocationSecurityMetadataSource - Adding web access control expression 'permitAll', for ExactUrl [processUrl='/pages/loginPage']
2017-01-01 12:11:47,682 5681 [main] DEBUG o.s.s.w.a.e.ExpressionBasedFilterInvocationSecurityMetadataSource - Adding web access control expression 'permitAll', for Ant [pattern='/logout', POST]
2017-01-01 12:11:47,682 5681 [main] DEBUG o.s.s.w.a.e.ExpressionBasedFilterInvocationSecurityMetadataSource - Adding web access control expression 'permitAll', for ExactUrl [processUrl='/pages/loginPage?logout=true']
2017-01-01 12:11:47,682 5681 [main] DEBUG o.s.s.w.a.e.ExpressionBasedFilterInvocationSecurityMetadataSource - Adding web access control expression 'permitAll', for Ant [pattern='/adminWebTheme/**']
2017-01-01 12:11:47,683 5682 [main] DEBUG o.s.s.w.a.e.ExpressionBasedFilterInvocationSecurityMetadataSource - Adding web access control expression 'hasRole('ADMIN')', for Ant [pattern='/pages/**']
2017-01-01 12:11:47,693 5692 [main] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Validated configuration attributes
2017-01-01 12:11:47,695 5694 [main] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Validated configuration attributes
2017-01-01 12:11:47,713 5712 [main] INFO o.s.s.w.DefaultSecurityFilterChain - Creating filter chain: org.springframework.security.web.util.matcher.AnyRequestMatcher#1, [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter#3a175162, org.springframework.security.web.context.SecurityContextPersistenceFilter#18acfe88, org.springframework.security.web.header.HeaderWriterFilter#7fd8c559, org.springframework.security.web.csrf.CsrfFilter#5c534b5b, org.springframework.security.web.authentication.logout.LogoutFilter#3a543f31, org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter#7569ea63, org.springframework.security.web.savedrequest.RequestCacheAwareFilter#772861aa, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter#7c1e32c9, org.springframework.security.web.authentication.AnonymousAuthenticationFilter#1640190a, org.springframework.security.web.session.SessionManagementFilter#8f2098e, org.springframework.security.web.access.ExceptionTranslationFilter#53ed09e8, org.springframework.security.web.access.intercept.FilterSecurityInterceptor#4743a322]
Now it seems to me all correctly configured.... but i can't protect my web application
Can anybody help me?
Thank you
Angelo
UPDATED AS SUGGESTED
As suggested I modified my Spring security configuration by doing:
#Override
protected void configure(HttpSecurity http) throws Exception
{
http
.authorizeRequests()
.antMatchers("/adminWebTheme/**")
.permitAll()
.antMatchers("/pages/**")
.authenticated()
.antMatchers("/pages/**")
.access("hasRole('ADMIN')")
.and()
.formLogin()
.loginPage("/pages/loginPage")
.permitAll()
.usernameParameter("username")
.passwordParameter("password")
.defaultSuccessUrl("/pages/adminHome")
.failureUrl("/pages/loginPage?error")
.and()
.logout()
.permitAll()
.logoutSuccessUrl("/pages/loginPage?logout")
.and()
.csrf()
.and()
.exceptionHandling()
.accessDeniedPage("/pages/accessDenied");
}
Nothing changed. It seems to me like if Spring security filter doesn't intercept urls... and I don't know the reason. I'm sure it's a configuration issue but I can't figure where I'm wrong...
Angelo

I figured what I was missing
I'm using and embedded Jetty where I manually added the spring dispatcher servlet
So I had to add the Spring security filter too....
In my jetty I added the following (the most important thing is the secFilter section):
DispatcherServlet springSvlt = new DispatcherServlet(context);
contextHandler.addServlet(new ServletHolder(springSvlt), MAPPING_URL);
contextHandler.addEventListener(new ContextLoaderListener(context));
contextHandler.setResourceBase(new ClassPathResource("webapp").getURI().toString());
//Filtro eTag
ServletHandler sh = new ServletHandler();
FilterHolder eTagFilter = sh.addFilterWithMapping(ShallowEtagHeaderFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST));
contextHandler.addFilter(eTagFilter, "/*", EnumSet.of(DispatcherType.REQUEST));
//Filtro Gzip
FilterHolder gZipFilter = sh.addFilterWithMapping(ShallowEtagHeaderFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST));
gZipFilter.setInitParameter("varyHeader", "true");
contextHandler.addFilter(gZipFilter, "/*", EnumSet.of(DispatcherType.REQUEST));
// //Filtro sicurezza
FilterHolder secFilter = new FilterHolder( new DelegatingFilterProxy("springSecurityFilterChain") );
contextHandler.addFilter(secFilter, "/*", EnumSet.allOf(DispatcherType.class));
Now it works correctly
Thank you to all and I hope this can be useful
Angelo

Related

CSRF token not provided with spring boot 2.7.1

I was using version 2.6.x of spring boot with success.
I've switched to 2.7.1. and adapted some of my security config to match the new format.
But now the CSRF token are no longer generated for me and injected in my login form, maybe the same with other forms, but I can't test it out.
Here is my security config
#Order(1)
#Bean
public SecurityFilterChain actuatorFilterChain(final HttpSecurity http) throws Exception {
// #formatter:off
return http
.requestMatchers().antMatchers("/jobs/**", "/actuator/**").and()
.authorizeRequests().antMatchers("/jobs/**", "/actuator/**").hasRole("SYSTEM").and()
.httpBasic()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.build()
;
// #formatter:on
}
#Bean
public SecurityFilterChain filterChain(final HttpSecurity http) throws Exception {
// #formatter:off
return http
.requestMatchers().antMatchers(applicationRoutes).and()
.authorizeRequests()
.antMatchers(applicationRoutes).hasAnyRole(applicationAuthorities).and()
.csrf().disabled().and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/")
.and()
.logout()
.logoutSuccessUrl("/")
.and()
.headers()
.httpStrictTransportSecurity().disable()
.and()
.build()
;
// #formatter:on
}
}
Here is my login page
<html>
<head>
</head>
<body>
<form th:action="#{/login}"
method="POST"
>
<div class="field">
<input type="text"
id="username"
name="username"
placeholder="&#xf007 Nom d'utilisateur"
style="font-family:Lato,'Helvetica Neue', FontAwesome">
</div>
<div class="field">
<input type="password"
id="password"
name="password"
placeholder="&#xf023 Mot de passe"
style="font-family:Lato,'Helvetica Neue', FontAwesome">
</div>
<button class="ui primary button"
style="width:100%"
type="submit">Connexion</button>
</form>
</body>
</html>
The error that is shown to me is a 405 saying /login doesn't support POST.
But the form sended to the browser doesn't include CSRF token in the form.
I suspect that I miss some new bits of configuration. But I don't know where to look for.
When adding http.requestMatchers() to a filter chain, the FilterChainProxy will ignore routes that do not match. In your case, /login is not matched by a filter chain. Therefore, no CSRF token is available for your login page.
Ensure /login is available in the applicationRoutes field in your example to fix the issue. You can add a permitAll rule to your /login route with .mvcMatchers("/login").permitAll() or adding .permitAll() to the .formLogin() DSL.

Spring Boot Thymeleaf variables blocking login page

I'm making a webshop in Spring Boot 2.1.1, with ThymeLeaf 3.0.11
My login page does not appear in every cases, everytime it wants to load it gives a "TemplateInputException" and fails to show up.
I figured it out, if I delete thymeleaf variables from the body or div tags (I mean th:with attributes), then it works until it reaches the next html tag with TL variables, after that, the html page just stops to render. What could be the problem? There is no scenario where i dont use those variables, I need them in the container tag. What is the relation between the Spring Boot login page and template variables?
I copy some code, if you need any more, please let me know.
Any help would be appreciated!
Here is my Webconfig:
#Configuration
public class WebConfig implements WebMvcConfigurer{
#Override
public void addViewControllers(ViewControllerRegistry registry){
registry.addViewController("/login").setViewName("auth/login");
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
}
My security config's configure method:
#Override
public void configure (HttpSecurity httpSec)throws Exception {
httpSec
.authorizeRequests()
.antMatchers("/", "/reg", "/login", "/css/**","/images/**",
"/js/**", "/register", "/error",
"/records", "/search", "/record", "/altercart",
"/showcart", "/category", "/viewchange",
"/images").permitAll()
.antMatchers("/admin").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.logoutSuccessUrl("/login?logout")
.permitAll();
}
My login page(using layout dialect):
<div layout:fragment="content">
<div>
<div th:if="${param.error}" th:text="#{login.error.wrongusernameorpassword}" class="col-12 error-message"/>
<div th:if="${param.logout}" th:text="#{logoutSuccess}" class="col-12 success-message"/>
<p th:text="#{logingreetings}" class="col-12"/>
<form method="post" th:action="#{login}">
<input type="text" name="username" th:placeholder="#{login.ph.username}" required class="col-12"/>
<br />
<input type="password" name="password" th:placeholder="#{login.ph.password}" required class="col-12"/>
<br />
<input type="submit" th:value="#{loginSubmitButton}" class="col-12"/>
<br /><br />
</form>
<br />
<a class="col-12 anchor" th:href="#{register}" th:text="#{misc.registration}">Registration</a>
</div>
</div>
Beggining of stack trace:
org.thymeleaf.exceptions.TemplateInputException: An error happened during
template parsing (template: "class path resource
[templates/auth/login.html]"

inMemoryAuthentication with Spring Boot

I've generated a Spring Boot web application using Spring Initializer, embedded Tomcat, Thymeleaf template engine, and package as an executable JAR file.
Technologies used:
Spring Boot 1.4.2.RELEASE, Spring 4.3.4.RELEASE, Thymeleaf 2.1.5.RELEASE, Tomcat Embed 8.5.6, Maven 3, Java 8
This is my security config class:
#Configuration
#EnableWebSecurity
#PropertySource("classpath:/com/tdk/iot/config/app-${APP-KEY}.properties")
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Value("${securityConfig.formLogin.loginPage}")
private String loginPage;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
.loginPage(loginPage)
.permitAll()
.loginProcessingUrl("/login")
.failureUrl("/login.html?error=true")
.defaultSuccessUrl("/books/list")
.and()
.exceptionHandling()
.accessDeniedPage("/denied")
.and()
.authorizeRequests()
.antMatchers("/mockup/**").permitAll()
.antMatchers("/books/**").permitAll()
.antMatchers("/welcome/**").authenticated()
.and()
.logout()
.permitAll()
.logoutSuccessUrl("/index.html");
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.passwordEncoder(new StandardPasswordEncoder())
.withUser("test1").password("test1").roles("ADMIN").and()
.withUser("test2").password("test2").roles("USER").and()
.withUser("test3").password("test3").roles("SUPERADMIN");
}
#Bean
public static PropertySourcesPlaceholderConfigurer propertyDefaultConfig() {
return new PropertySourcesPlaceholderConfigurer();
}
}
Here the LoginController
#Controller
public class LoginController {
#RequestMapping(value={ "/", "/tdk/login"}, method = { RequestMethod.POST,RequestMethod.GET})
public String welcome(Map<String, Object> model) {
return "tdk/login";
}
}
and the template:
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
<div class="wrap">
<div class="login">
<div class="logo"></div>
<form th:action="#{/login.html}" method="post">
<p th:if="${loginError}" class="error">Wrong user or password</p>
<div class="input_label"><i class="fa fa-user"></i><input type="text" name="user" placeholder="User" /></div>
<div class="input_label"><i class="fa fa-key"></i><input type="password" name="pass" placeholder="Password" /></div>
<input type="submit" value="LOGIN" />
</form>
<div class="forget">
<!-- Do you forgot your password?<br/> -->
<br/>
</div>
</div>
</div>
</body>
</html>
but when I access with test1 / test1 I got this error:
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Sun Mar 05 20:16:11 CET 2017
There was an unexpected error (type=Method Not Allowed, status=405).
Request method 'POST' not supported
Your login page calls /login.html with HTTP POST, but your server doesn't provide such a request mapping.
The configured URL in your Spring Security configuration:
.loginProcessingUrl("/login")
is not matching the URL in your login page:
<form th:action="#{/login.html}" method="post">
See also AbstractAuthenticationFilterConfigurer#loginProcessingUrl:
Specifies the URL to validate the credentials.
try this code
.failureUrl("/tdk/login?error=true")
Controller
#Controller
public class LoginController {
#RequestMapping(value={ "/", "/tdk/login"},params = {"error"},method=RequestMethod.POST)
public String welcome(#RequestParam(value = "error", required = false) int error , ModelMap model) {
if (error == 1) {
model.addAttribute("msg", "Invalid Username or Password");
return "tdk/login";
}
else{
return "redirect:home";
}
}
}
Default method controller for #RequestMapping is GET, not POST.
You need to specify the method on the #requestMapping.
#RequestMapping(value={ "/", "/tdk/login"}, method = RequestMethod.POST)

Spring Security / MVC / JPA --> Request method 'POST' not supported

I am having errors login from the HTML using Spring Security, Spring MVC and JPA.
This is my login.HTML
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head lang="en" xmlns:th="http://www.thymeleaf.org">>
<title>Spring Framework Guru</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
</head>
<body class="security-app">
<div class="details">
<h2>Spring Security - App</h2>
</div>
<form action="/login" method="post">
<div class="lc-block">
<div>
<input type="text" class="style-4" name="username"
placeholder="User Name" />
</div>
<div>
<input type="password" class="style-4" name="password"
placeholder="Password" />
</div>
<div>
<input type="submit" value="Sign In" class="button red small" />
</div>
<th:if test="${param.error ne null}">
<div class="alert-danger">Invalid username and password.</div>
</th:if>
<th:if test="${param.logout ne null}">
<div class="alert-normal">You have been logged out.</div>
</th:if>
</div>
<input type="hidden" name="${_csrf.parameterName}"
value="${_csrf.token}" />
</form>
</body>
</html>
This is WebSecurity class:
#Configuration
#EnableWebSecurity
#ComponentScan(basePackageClasses = CustomUserDetailsService.class)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private UserDetailsService userDetailsService;
#Autowired
public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordencoder());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/hello").access("hasRole('ROLE_ADMIN')")
.anyRequest().permitAll()
.and()
.formLogin().loginPage("/login")
.usernameParameter("username").passwordParameter("password")
.and()
.logout().logoutSuccessUrl("/login?logout")
.and()
.exceptionHandling().accessDeniedPage("/403")
.and()
.csrf();
}
#Bean(name = "passwordEncoder")
public PasswordEncoder passwordencoder() {
return new BCryptPasswordEncoder();
}
}
UserDetails service class:
#Service("customUserDetailsService")
public class CustomUserDetailsService implements UserDetailsService {
private final UserRepository userRepository;
private final UserRolesRepository userRolesRepository;
#Autowired
public CustomUserDetailsService(UserRepository userRepository, UserRolesRepository userRolesRepository) {
this.userRepository = userRepository;
this.userRolesRepository = userRolesRepository;
}
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUserName(username);
if (null == user) {
throw new UsernameNotFoundException("No user present with username: " + username);
} else {
List<String> userRoles = userRolesRepository.findRoleByUserName(username);
return new CustomUserDetails(user, userRoles);
}
}
}
I always have 405 error:
2016-10-16 12:15:30.710 WARN 2932 --- [nio-8080-exec-3] o.s.web.servlet.PageNotFound : Request method 'POST' not supported
Any ideas why is not calling the "configure(HttpSecurity http)". Am I missing something?
Thank you very much
Andres
Try adding
.formLogin().loginPage("/xxx").permitAll()
.defaultSuccessUrl("/xxx")
.failureUrl("/xxx?error")
In addition
One typical reason in Spring MVC Applications for controller methods and pages not found is Spring's weird mapping convention to build URLs by adding a new link (or the form action="x") to the end of current URL. 'Request Method POST Not Supported' only means that your request is pointed to somewhere where nothing is accepting the POST request => URL mapping fails. On JSP sites you should always specify URLs like
<form action="${pageContext.request.contextPath}/login" method="post">
or with JSTL
<c:url value="/login" var="loginUrl" />
<form action="${loginUrl}" method="post">
Then you can be sure that your link is set right after the application root in URL. This will save you from a lot of unnecessary problems in the future.

how could I use csrf in spring security

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.
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.
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

Resources