I'm using Spring security for my project, and this is my configuration.
protected void configure(HttpSecurity http) throws Exception {
http.
authorizeRequests()
.antMatchers("/home").hasRole("USER")
.antMatchers("/edit-information/**").hasRole("USER")
.antMatchers("/admin/**").hasAnyRole("ADMIN_STAFF","ADMIN_MANAGER")
.antMatchers("/admin/employee").hasRole("ADMIN_MANAGER")
.and()
.formLogin()
.loginPage("/home/login")
.loginProcessingUrl("/j_spring_security_check")
.usernameParameter("email")
.passwordParameter("password")
.defaultSuccessUrl("/",true)
.failureUrl("/home/login-fail")
.and()
.exceptionHandling()
.accessDeniedPage("/403");
}
So it is my idea.
I want all ADMIN can log in to /admin/** but in /admin/** I have /admin/employee. I just want role ADMIN_MANAGER can log in here only.
But .antMatchers("/admin/**").hasAnyRole("ADMIN_STAFF","ADMIN_MANAGER") is already let ADMIN_STAFF log in to /admin/employee. I tried to add .antMatchers("/admin/employee").hasRole("ADMIN_MANAGER") but it did not work!
I do believe the problem is in the ordering for that antMatchers. The order of the rules matters and the more specific should come first, so instead of this:
.antMatchers("/admin/**").hasAnyRole("ADMIN_STAFF","ADMIN_MANAGER")
.antMatchers("/admin/employee").hasRole("ADMIN_MANAGER")
You can try this:
.antMatchers("/admin/employee").hasRole("ADMIN_MANAGER")
.antMatchers("/admin/**").hasAnyRole("ADMIN_STAFF","ADMIN_MANAGER")
Related
To give some context, I'm building a PWA (Progressive Web App) for myself and some friends as a test project. I'm using basic authentication.
As it is a PWA I want it to behave like other apps do, which includes not having to log in every few days keeping the user logged in. Disabling the timeout may not be the best way as it gives security risks but for now it should do just fine.
I already tried to increase the timeout setting to a high number and use the -1 value like below.
server.servlet.session.timeout=9999999999
spring.session.timeout=9999999999
and
server.servlet.session.timeout=-1
spring.session.timeout=-1
But both do not work.
This is how I configured my security:
protected void configure(final HttpSecurity http) throws Exception {
http
.headers().cacheControl().disable().and()
.authorizeRequests()
.antMatchers(HttpMethod.POST, "/api/user").permitAll()
.antMatchers("/api/*").authenticated()
.anyRequest().permitAll()
.and()
.cors()
.and()
.csrf()
.ignoringAntMatchers("/logout")
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.and()
.httpBasic()
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.clearAuthentication(true);
}
As mentioned, after a few days the application will still timeout and give me an 401 error (even though the cookies still exists) which means the user has to log in again.
Does anyone know how I can make the session really long or indefinitely. And if this is not possible which other solution could I use to solve this problem?
I am trying to understand this spring-boot project:hbs-spring-boot-jpa-mysql-thymeleaf-security
In the HbsController the code is
As I know when I input the localhost:8080/hbs, I should see the index page right? but I can only see thisAnd I look into the project I can't find the login page? where is it? please help me.
in the SecurityConfig you might have the /hbs mapping with authorisation required.
in this example from https://www.baeldung.com/spring-security-login
#Override
protected void configure(final HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/anonymous*").anonymous()
.antMatchers("/login*").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login.html")
.loginProcessingUrl("/perform_login")
.defaultSuccessUrl("/homepage.html", true)
//.failureUrl("/login.html?error=true")
.failureHandler(authenticationFailureHandler())
.and()
.logout()
.logoutUrl("/perform_logout")
.deleteCookies("JSESSIONID")
.logoutSuccessHandler(logoutSuccessHandler());
}
".antMatchers("/admin/**").hasRole("ADMIN")" forces the acces to only "ADMIN" users and redirects them to /login
try to modify your configuration class that implements WebSecurityConfigurerAdapter and it will work
I think it is because there is spring boot security implemented/included in the pom file/project: https://spring.io/guides/gs/securing-web/
You can see the spring security configuration in the class "SpringSecurity.java" in the folder "security". You can modify it there or look up what the credentials are.
I'm using Spring Boot and Thymeleaf. I have a custom 404 template page defined in src/main/resources/templates/error/404.html
This works properly when users are logged in.
However, when they are logged out, they do not get any type of 404 page, they just get redirected back to /login.
I'm thinking my security configuration needs to change but not sure what.
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/","/register*","/resetPassword","/forgotPassword","/login","/404").permitAll()
.antMatchers("/admin/**").hasAuthority("ADMIN").anyRequest()
.authenticated().and().formLogin().loginPage("/login").failureUrl("/login?error")
.defaultSuccessUrl("/dashboard").successHandler(successHandler)
.usernameParameter("email").passwordParameter("password")
.and().logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessUrl("/login?logout").and()
.exceptionHandling().accessDeniedPage("/access-denied");
}
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/error**","/resources/**", "/static/**", "/css/**", "/js/**", "/img/**");
}
First of all I encourage you to use indentation when using java config to configure your security for your spring application. It helps with readability.
Note all top level methods on the first indentation (authRequest,formLogin,logout) all configure/update the HTTP object it self. All these elements are from the org.springframework.security.config.annotation.web.builders.HttpSecurity class.
The children of these classes further refine the HTTP security configuration.
http
.authorizeRequests()
.antMatchers("/","/register*","/resetPassword","/forgotPassword","/login","/404")
.permitAll()
.antMatchers("/admin/**").hasAuthority("ADMIN")
.anyRequest().authenticated() // <--------
.and()
.formLogin()
.loginPage("/login")
.failureUrl("/login?error")
.defaultSuccessUrl("/dashboard")
.usernameParameter("email").passwordParameter("password")
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/login?logout")
.and()
.exceptionHandling()
.accessDeniedPage("/access-denied");
Note .anyRequest().authenticated() is specifically stating that any request must be authenticated. So when you attempt to goto any missing url on your domain it will ask you to login rather than goto the 404 page.
So if you remove that statement it and then try an goto a missing url page it will redirect you to a 404 page.
If you remove .anyRequest().Authenticated() then you can log in without authenticated.
Therefore, do not try to delete. For example, if you go to the address "http://localhost:8080/user", then you will be taken to the authorization page. And if you try to enter the page "http://localhost:8080/user/" then you will be taken to the user page. Please note that links differ only by the forward slash at the end. Of course if you remove ".anyRequest().Authenticated()" in this case you need to add more parameters to antMatchers like "/user" and "/user/"
Therefore, be careful and attentive.
Im working in a java-springs web application with custom security evaluator method,
i need to pass the URL hit by user as a parameter for the method permissionEvaluator.canUserAccessPage(URLHitByUser).
How to get URL hit by user.
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
//.antMatchers("/view/**").permitAll()
.antMatchers("/assets/**").permitAll()
.antMatchers("/view/admin.html").access("#permissionEvaluator.canUserAccessPage(URLHitByUser)")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login").usernameParameter("username").passwordParameter("password")
.defaultSuccessUrl("/index")
.permitAll()
// [...]
}
If you intention is controlling the access to certain roles,this can be achieved by using sec:intercept-url in applicationContext-security-preauth.xml.
Thanks
I followed the guide here: http://spring.io/guides/gs/rest-service/ to build my rest service example and now I am trying to enable the CSRF protection. I read that it should be enabled by default, so if I DON'T include:
http.csrf().disable()
in my WebSecurityConfigurerAdapter configuration, the CSRF protectection should be enabled by default, but it does not seem to to be the case. The problem is that the X-CSRF-TOKEN is not generated and not included in my HTTP response in any way.
What am I expected to do, to have the x-csrf-token generated and included in the response and, of course, the csrf protection fully working?
I noticed that, with a similar spring mvc configuration, I get the x-csrf-token generated simply including:
< security:csrf disabled="false"/>
in my security configuration file. But, with spring boot maybe I am getting something wrong and there is no way to have the csrf token generated. Can anybody help me, perhaps pointing me to a working example? My security configuration is:
#Override
protected void configure(HttpSecurity http) throws Exception
{
http
// .csrf().disable()
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.httpBasic()
.authenticationEntryPoint(new RestAuthenticationEntryPoint())
.and()
.formLogin()
.successHandler(new RestAuthenticationSuccessHandler())
.failureHandler(new SimpleUrlAuthenticationFailureHandler())
.and()
.logout()
.logoutSuccessHandler(new RestLogoutSuccessHandler());
}
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception
{
auth.userDetailsService(restUserDetailService);
}
To include the CSRF Token in your csrf protection, you can include CSRFTokenRepository to generate tokens. To illustrate in your case adding a simple line is enough:
#Override
protected void configure(HttpSecurity http) throws Exception
{
http.
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) //HERE ! Defaults XSRF-TOKEN as cookie name and X-XSRF-TOKEN as header name
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.httpBasic()
.authenticationEntryPoint(new RestAuthenticationEntryPoint())
.and()
.formLogin()
.successHandler(new RestAuthenticationSuccessHandler())
.failureHandler(new SimpleUrlAuthenticationFailureHandler())
.and()
.logout()
.logoutSuccessHandler(new RestLogoutSuccessHandler());}
Using Spring security 5.3.0.Final, one of the ways you can generate the CSRF token is by setting it in the cookie using the following code below.
http.csrf(csrf -> csrf.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()))
You also need to include the generated CSRF token in your request for the server to authorize.
<form>
<input type="hidden" name="_csrf" value="${cookie['XSRF-TOKEN'].getValue()}" />
//Code goes here
</form>
In the event you're using a JS framework, you need to include the token by setting it in the request header.
Here is an example for a JQuery ajax call.
// Get the CSRF token from the cookie
const csrfCookie= document.cookie.replace(/(?:(?:^|.*;\s*)XSRF-TOKEN\s*\=\s*([^;]*).*$)|^.*$/, '$1');
// Add the CSRF token to each ajax request header
settings.beforeSend = function(xhr) {
xhr.setRequestHeader('X-XSRF-TOKEN', springCsrfCookie);
};
$.ajax(settings);
There are other implementations that will suit your needs documented in the following link by Spring | https://docs.spring.io/spring-security/site/docs/5.3.0.RELEASE/reference/html5/#servlet-csrf
We had pretty similar issue during our security tests where we suspected that we accidentally disable csfr in configure method of websecurityconfig class,by default it is enabled. by changing the congfigure method as shown below , we had spring automatically generate csfr tokens.
websecurityconfig class configure method==>
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/login","/loginError","/home","/interruption").permitAll()
.antMatchers("/admin").hasAuthority(Roles.ROLE_PREFIX.role()+Roles.HALLEYYNT01.role())
.antMatchers("/requests").hasAuthority(Roles.ROLE_PREFIX.role()+Roles.CCHALLEYLOGIN.role())
.antMatchers("/solrequests").hasAuthority(Roles.ROLE_PREFIX.role()+Roles.SOLHALLEYLOGIN.role())
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
//.failureUrl("/loginError")
.loginProcessingUrl("/authenticate")
.defaultSuccessUrl("/")
.and()
.logout().clearAuthentication(true).invalidateHttpSession(true).deleteCookies("JSESSIONID")
.logoutSuccessUrl("/login");
//.and()
//.exceptionHandling().accessDeniedHandler(accessDeniedHandler);
}