spring security - expiredUrl not working - java

I need to configure expired-url in my Spring MVC application. Here is my effort, but has no effect:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.addFilterBefore(adminAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(customerAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
.csrf()
.disable()
.authorizeRequests()
.antMatchers("...", "...", "...").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/admin/login")
.and()
.logout()
.addLogoutHandler(customLogoutHandler())
.logoutSuccessHandler(customLogoutSuccessHandler())
.logoutUrl("/logout")
.deleteCookies("remove")
.invalidateHttpSession(true)
.permitAll()
.and()
.sessionManagement()
.maximumSessions(1)
.expiredUrl("/expired");
}
This does not have any effect and when the user's session times out, spring does not redirect him to /expired url and just redirects him to /admin/login url.
Update:
I tried suggested solutions in the comments and answer, but did not see any effect. Also I removed addLogoutHandler(), logoutSuccessHandler() and two addFilterBefore() at beginning of method, but not working.
Also I tried another solution in this way:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.addFilterBefore(sessionManagementFilter(), SessionManagementFilter.class)
.csrf()
.disable()
.authorizeRequests()
.antMatchers("...", "...", "...").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/admin/login")
.and()
.logout()
.logoutUrl("/logout")
.deleteCookies("remove")
.invalidateHttpSession(true)
.permitAll();
}
#Bean
public SessionManagementFilter sessionManagementFilter() {
SessionManagementFilter sessionManagementFilter = new SessionManagementFilter(httpSessionSecurityContextRepository());
sessionManagementFilter.setInvalidSessionStrategy(simpleRedirectInvalidSessionStrategy());
return sessionManagementFilter;
}
#Bean
public SimpleRedirectInvalidSessionStrategy simpleRedirectInvalidSessionStrategy() {
SimpleRedirectInvalidSessionStrategy simpleRedirectInvalidSessionStrategy = new SimpleRedirectInvalidSessionStrategy("/expired");
return simpleRedirectInvalidSessionStrategy;
}
#Bean
public HttpSessionSecurityContextRepository httpSessionSecurityContextRepository(){
HttpSessionSecurityContextRepository httpSessionSecurityContextRepository = new HttpSessionSecurityContextRepository();
return httpSessionSecurityContextRepository;
}
Could anyone help me to solve this problem?

ConcurrentSessionFilter will redirect to expiredUrl, if the valid session ID is marked as expired in SessionRegistry, see Spring Security reference:
- expired-url The URL a user will be redirected to if they attempt to use a session which has been "expired" by the concurrent session controller because the user has exceeded the number of allowed sessions and has logged in again elsewhere. Should be set unless exception-if-maximum-exceeded is set. If no value is supplied, an expiry message will just be written directly back to the response.
SessionManagementFilter will redirect to invalidSessionUrl, if the session ID is not valid (timeout or wrong ID), see Spring Security reference:
If the user is not currently authenticated, the filter will check whether an invalid session ID has been requested (because of a timeout, for example) and will invoke the configured InvalidSessionStrategy, if one is set. The most common behaviour is just to redirect to a fixed URL and this is encapsulated in the standard implementation SimpleRedirectInvalidSessionStrategy. The latter is also used when configuring an invalid session URL through the namespace,as described earlier.
Both URLs (expiredUrl, invalidSessionUrl) have to be configured as permitAll().
BTW: If you want to use Concurrent Session Control with maximumSessions you have to add HttpSessionEventPublisher to your web.xml:
Concurrent Session Control
If you wish to place constraints on a single user’s ability to log in to your application, Spring Security supports this out of the box with the following simple additions. First you need to add the following listener to your web.xml file to keep Spring Security updated about session lifecycle events:
<listener>
<listener-class>
org.springframework.security.web.session.HttpSessionEventPublisher
</listener-class>
</listener>

I tried the Ali Dehghani's solution(in the comments) in this way:
.sessionManagement().maximumSessions(1).and().invalidSessionUrl("/expired");
And as The Coder said, add "/expired" in the permitted urls and the problem solved. Thank you everybody who has paid attention to my problem, especially Ali Dehghani and The Coder, for their useful comments.

Ideally your UX should simply redirect your user back to the login page. I guess you see the requirement of having a dedicated /expired page because of Spring MVC - change security settings dynamically where you informed about your need of having separate login masks. If the workaround (the one that I described in my answer on your other question) works for you, you could maybe drop your requirement of having a dedicated /expired page and redirect the user to the correct login page directly using teh solution approach number (2). How about that?
Nevertheless, to answer your current question...
I'm not sure if it works but give it a try and change your code
//...
.sessionManagement()
.maximumSessions(1)
.expiredUrl("/expired");
}
to
//...
.sessionManagement().sessionFixation().newSession().maximumSessions(1)
.expiredUrl("/expired")
.sessionRegistry(sessionRegistry());
}
#Bean
public SessionRegistry sessionRegistry() {
SessionRegistry sessionRegistry = new SessionRegistryImpl();
return sessionRegistry;
}
In case it doesn't work, could you then post the code of your customLogoutHandler() and customLogoutSuccessHandler()? You are using Spring MVC outside of Spring Boot, correct?

If you use UserDetails and UserDetailsService then it should be because your UserDetails implementation class there is no Override hashCode () and equals (Object obj) method. This is my implementation class for UserDetails:
public class MyUser implements UserDetails {
private String username;
private String password;
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return null;
}
#Override
public String getPassword() {
return null;
}
#Override
public String getUsername() {
return null;
}
#Override
public boolean isAccountNonExpired() {
return false;
}
#Override
public boolean isAccountNonLocked() {
return false;
}
#Override
public boolean isCredentialsNonExpired() {
return false;
}
#Override
public boolean isEnabled() {
return false;
}
#Override
public int hashCode() {
return username.hashCode();
}
#Override
public boolean equals(Object obj) {
return this.toString().equals(obj.toString());
}
}

Related

Java Spring cannot logout properly

I understand this question has been asked before, but none of what worked for the others worked for me. That said, here it is:
After setting up .logout() and its relevant associate methods, I still cannot make my Spring server logout properly. To be precise, this is the sequence I'm following:
POST login, get token
Use token for other HTTP requests, such as a standard GET for DB data
Logout using the vanilla logout URL
Try to do step 2 again, to see if logout was successful.
At 4, for a reason that is unknown to me, I'm still able to GET the data, which is wrong.
Some of the things I've tried are:
.clearAuthentication(true).invalidateHttpSession(true)
Setting up the following bean on my SecurityConfig:
#Bean
public static ServletListenerRegistrationBean httpSessionEventPublisher() {
return new ServletListenerRegistrationBean(new HttpSessionEventPublisher());
}
None of it worked. Below are my security configurations. Any clues and help is much appreciated, and I thank you in advance.
SecurityConfig.java
#Configuration
public class SecurityConfig {
#Autowired
private AuthenticationManager authenticationManager;
private final AuthSuccessHandler authSuccessHandler;
private final JwtUserDetailsService jwtUserDetailsService;
private final String secret;
SecurityConfig(AuthSuccessHandler authSuccessHandler, JwtUserDetailsService jwtUserDetailsService, #Value("${jwt.secret}") String secret) {
this.authSuccessHandler = authSuccessHandler;
this.jwtUserDetailsService = jwtUserDetailsService;
this.secret = secret;
}
#Bean
public static ServletListenerRegistrationBean httpSessionEventPublisher() {
return new ServletListenerRegistrationBean(new HttpSessionEventPublisher());
}
#Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.cors()
.and()
.csrf()
.disable()
.authorizeHttpRequests((auth) -> {
try {
auth
.requestMatchers("/user").hasRole("USER")
.requestMatchers("/admin").hasRole("ADMIN")
.requestMatchers("**/encoding-results/**", "**/encoding-results").hasAnyRole("ADMIN")
.requestMatchers("**/video/**").hasAnyRole("ADMIN")
.requestMatchers("**/codec/**").hasAnyRole("ADMIN")
.requestMatchers("**/auth/**").permitAll()
.anyRequest().authenticated()
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.addFilter(authenticationFilter())
.addFilter(new JwtAuthorizationFilter(authenticationManager, jwtUserDetailsService, secret))
.logout(logout -> logout
.clearAuthentication(true)
.logoutUrl("/logout")
.invalidateHttpSession(true)
.deleteCookies("JSESSIONID"))
.exceptionHandling()
.authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED));
} catch (Exception e) {
throw new RuntimeException(e);
}
})
.httpBasic(Customizer.withDefaults());
return http.build();
}
#Bean
public JsonObjectAuthenticationFilter authenticationFilter() throws Exception {
JsonObjectAuthenticationFilter filter = new JsonObjectAuthenticationFilter();
filter.setAuthenticationSuccessHandler(authSuccessHandler);
filter.setAuthenticationManager(authenticationManager);
return filter;
}
}
You cant logout a JWT, a JWT is valid as long as you have set the validation time to be.
OWASP has written about this problem No Built-In Token Revocation by the User
You have written a custom login that issues tokens. The server has no idea how many tokens that have been issued and which tokens that are logged in or not.
So no you can't logout the user, unless you keep some form of state of the issued tokens on the server side, as in storing the tokens in a database and invalidating them when someone does a logout.
And ofc deleting the sessionid cookie wont do anything since you are not using session cookies.
This is the exact reason why you shouldn't be using JWTs as session replacements.
Stop using JWT for sessions
Stop using JWT for sessions, part 2
JSON Web Tokens (JWT) are Dangerous for User Sessions
Why JWTs Suck as Session Tokens

Spring Boot post request handler not firing

Thanks for looking into my issue.
I'm practicing with Spring Boot and Spring Security. I've created a simple project with basic registration, but I can't get logging in to work. I'm trying to manually log users in in a POST: /login method, but the method is not firing. When I try to login with POST: /login, it just 302 redirects to GET /login. I'm pretty sure I've set up the security configuration and the method annotations correctly. But the post method isn't even running. (I know because I have a print statement in my post method that's not printing anything even when I start the application and create a user and log in.) How can I fix this?
(I'm not sure if the post method will actually log users in correctly, I just want to get it to run so I can figure that part out.)
The full code is here: https://github.com/Skyler827/SpacePong/tree/7530377a634f1a2fe55ce490402d947616439e72
The Security configurer method:
protected void configure (HttpSecurity http) throws Exception {
http
.csrf()
.ignoringAntMatchers("/h2/**")
.and()
.headers()
.frameOptions().sameOrigin().and()
.authorizeRequests()
.antMatchers("/login", "/register", "/h2/**").permitAll()
.antMatchers(HttpMethod.POST, "/login").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginProcessingUrl("/login")
.loginPage("/login")
.failureUrl("/login?error=true")
.successForwardUrl("/")
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/")
.permitAll();
}
And the Controller which should be working but isn't:
#Controller
#RequestMapping("/login")
public class LoginController {
private final AuthenticationManager authManager;
private final PlayerService playerService;
public LoginController(AuthenticationManager authManager, PlayerService playerService) {
this.authManager = authManager;
this.playerService = playerService;
}
#GetMapping
public String getLogin(Model model) {
model.addAttribute("playerdto", new PlayerDto());
System.out.println("running getLogin()");
return "login";
}
#PostMapping
public String postLogin(#ModelAttribute("playerdto") PlayerDto playerDto, Model model) {
System.out.println("running postLogin()");
Player player = playerService.getPlayerByName(playerDto.getUsername());
if (player == null) {
model.addAttribute("error", "invalid login");
return "login";
}
UsernamePasswordAuthenticationToken authReq = new UsernamePasswordAuthenticationToken(
playerDto.getUsername(), playerDto.getPassword());
Authentication auth = authManager.authenticate(authReq);
return "redirect:/";
}
}
The Form Login sample has an example of how to configure a custom login page. Some usual issues are not using the correct form action (e.g. action="/login"), incorrectly named form inputs (e.g. name="username", name="password") and missing hidden CSRF input (e.g. type="hidden" name="_csrf" value="...").
The most important detail to remember is that when configuring .formLogin(), Spring Security's filter chain is handling the POST /login request and returning a response prior to your controller, even when .antMatchers("/login").permitAll() is used. This is why you don't see anything hitting your controller method.
While I don't recommend it in most cases, you can play around with handling the POST /login request yourself by simply omitting the .formLogin() part of the DSL. When you do this, you are responsible for setting up the SecurityContext yourself.
I was able to find a workaround solution; I still can't get the custom controller method to execute, but I can log users in, which was my goal.
This project is using Java 17, by the way.
I enabled user login to work by deleting the whole postLogin() method in the controller, and deleting all of the configurations under formLogin() in the configure(HttpSecurity http) method. Once I did this, I no longer had my custom login page, but I did have a default login page, and it did work.
I tried to add the .loginPage("/login") directive back into the configure method to specify the custom login page, but that caused the login form to go back to 302 redirecting to itself, even after my incorrect controller was deleted.
My corrected configure method:
protected void configure (HttpSecurity http) throws Exception {
http
.csrf()
.ignoringAntMatchers("/h2/**")
.and()
.headers()
.frameOptions().sameOrigin().and()
.authorizeRequests()
.antMatchers("/login", "/register", "/h2/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/")
.permitAll();
}
My corrected controller:
#Controller
#RequestMapping("/login")
public class LoginController {
private final AuthenticationManager authManager;
private final PlayerService playerService;
public LoginController(AuthenticationManager authManager, PlayerService playerService) {
this.authManager = authManager;
this.playerService = playerService;
}
#GetMapping
public String getLogin(Model model) {
model.addAttribute("playerdto", new PlayerDto());
System.out.println("running getLogin()");
return "login";
}
}

Why JSESSIONID doesn't change after logging in when using a custom security filter in Spring Boot?

I've noticed that JSESSIONID doesn't change after logging in when using a custom security
filter.
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.addFilterBefore(authenticationFilter(), UsernamePasswordAuthenticationFilter.class)
.authorizeRequests()
.antMatchers("/", "/home").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
public UsernamePasswordAuthenticationFilter authenticationFilter() throws Exception {
CustomFilter customFilter = new CustomFilter();
customFilter.setAuthenticationManager(authenticationManagerBean());
return customFilter;
}
Even if I put sessionManagement().sessionFixation().newSession() but when I remove the custom filter JESESSIONID does get refresed every time I log in and out.
Does anybody know why ? I would like to understand.
The custom filter has the same implementation of UsernamePasswordAuthenticationFilter
public class CustomFilter extends UsernamePasswordAuthenticationFilter {
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
if (!request.getMethod().equals("POST")) {
throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
} else {
String username = this.obtainUsername(request);
String password = this.obtainPassword(request);
if (username == null) {
username = "";
}
if (password == null) {
password = "";
}
username = username.trim();
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
this.setDetails(request, authRequest);
return this.getAuthenticationManager().authenticate(authRequest);
}
}
}
I build the simple project fallowing this guide: https://spring.io/guides/gs/securing-web/
The short answer is that the default SessionAuthenticationStrategy in UsernamePasswordAuthenticationFilter is a NullAuthenticatedSessionStrategy.
By simply extending UsernamePasswordAuthenticationFilter and creating a new instance, the custom filter will use a NullAuthenticatedSessionStrategy.
When Spring Security creates the UsernamePasswordAuthenticationFilter from the form login configuration, it sets the SessionAuthenticationStrategy to the strategy configured in HttpSecurity, defaulting to ChangeSessionIdAuthenticationStrategy.
If you trace through the code, you can see how this happens.
When configuring http.formLogin() Spring Security creates a FormLoginConfigurer which extends AbstractAuthenticationFilterConfigurer.
The FormLoginConfigurer constructor creates a new instance of UsernamePasswordAuthenticationFilter.
Later, when the configure method is called on the FormLoginConfigurer, you will notice various properties are set on the filter, one of which is the SessionAuthenticationStrategy.
SessionAuthenticationStrategy sessionAuthenticationStrategy = http
.getSharedObject(SessionAuthenticationStrategy.class);
if (sessionAuthenticationStrategy != null) {
this.authFilter.setSessionAuthenticationStrategy(sessionAuthenticationStrategy);
}
If you look at the SessionManagementConfigurer, you will notice that the default strategy is ChangeSessionIdAuthenticationStrategy.
The SessionAuthenticationStrategy#onAuthentication is later called in the doFilter method of UsernamePasswordAuthenticationFilter.
That is why the filter configured by Spring Security will change the session ID after login, while a new instance of the filter, with no properties set, will not.

How to call rest endpoint via Spring restTemplate that is protected by Keycloak

Preconditions
I have two Java Spring applications(App 'A' and App 'B') that were created via JHipster(monolithic application). Both applications uses keycloak for authentication/authorization.
Both applications have an angular frontend and support login via ouath (spring-security). Here ist my SecurityConfiguration of Application A and B:
#Configuration
#Import(SecurityProblemSupport.class)
#EnableOAuth2Sso
#EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
private final CorsFilter corsFilter;
private final SecurityProblemSupport problemSupport;
public SecurityConfiguration(CorsFilter corsFilter, SecurityProblemSupport problemSupport) {
this.corsFilter = corsFilter;
this.problemSupport = problemSupport;
}
#Bean
public AjaxLogoutSuccessHandler ajaxLogoutSuccessHandler() {
return new AjaxLogoutSuccessHandler();
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Bean
public SecurityEvaluationContextExtension securityEvaluationContextExtension() {
return new SecurityEvaluationContextExtension();
}
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring()
.antMatchers(HttpMethod.OPTIONS, "/**")
.antMatchers("/app/**/*.{js,html}")
.antMatchers("/i18n/**")
.antMatchers("/content/**")
.antMatchers("/swagger-ui/index.html")
.antMatchers("/test/**")
.antMatchers("/h2-console/**");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.and()
.addFilterBefore(corsFilter, CsrfFilter.class)
.exceptionHandling()
.authenticationEntryPoint(problemSupport)
.accessDeniedHandler(problemSupport)
.and()
.logout()
.logoutUrl("/api/logout")
.logoutSuccessHandler(ajaxLogoutSuccessHandler())
.permitAll()
.and()
.headers()
.frameOptions()
.disable()
.and()
.authorizeRequests()
.antMatchers("/api/profile-info").permitAll()
.antMatchers("/api/**").authenticated()
.antMatchers("/management/health").permitAll()
.antMatchers("/management/**").hasAuthority(AuthoritiesConstants.ADMIN)
.antMatchers("/v2/api-docs/**").permitAll()
.antMatchers("/swagger-resources/configuration/ui").permitAll()
.antMatchers("/swagger-ui/index.html").hasAuthority(AuthoritiesConstants.ADMIN);
}
}
In App B i also have an ResourceServerConfiguration. This checks if the header contains an "Authorization" key. If true, the user can login via JWT(Bearer Authentication). I tested this via Postman and it works fine:
#Configuration
#EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
#Override
public void configure(final HttpSecurity http) throws Exception {
http
.requestMatcher(new RequestHeaderRequestMatcher("Authorization")).authorizeRequests()
.anyRequest().authenticated();
}
}
Further more both apps are in the same keycloak realm and have the access-type "public".
Problem:
Now i want to call an endpoint of App B via an Spring RestTemplate from App A. The problem is, that i do not have an access_token that i can put in my rest request/restTemplate. When i look in my request that is send from my frontend, i only got an JSESSIONID. There is no access_token/JWT in the header.
Question
Is there a way to get the access_token of the current user out of the JSESSIONID/the HttpSession or the spring security context? Do i need something like a Tokenstore where i store every token that comes from keycloak?
Did anyone else have similar problems or any idea how i could solve that problem?
After some research it turns out that the problem lies within the generated jhipster code.
I followed the authentication process in the application and saw, that there was a call to the /account endpoint directly after authentication, where the user information were retrieved. The call is triggerd by the frontend. First time this endpoint is called, there is a principal with a bearer token available. Within the /account endpoint, a call to the userService with the principal object is performed. More precisley
getUserFromAuthentication(OAuth2Authentication authentication)
is called. Within this method there is a part that replaces the OAuth2Authentication with a new UsernamePasswordAuthenticationToken and inserts it into the SecurityContext:
UsernamePasswordAuthenticationToken token = getToken(details, user,
grantedAuthorities);
authentication = new OAuth2Authentication(authentication.getOAuth2Request(), token);
SecurityContextHolder.getContext().setAuthentication(authentication);
So after that, the access_token is lost. I am not quite sure, why it was replaced with the new OAuth2Authentication, but i tend to extend this part and keep the access_token in my securityContext for further restcalls.

Order of Java Config SecurityBuilder's

I'm developing a web application unsing Spring Security 4.0.0's Java Config instead of xml config. I'm using ObjectPostProcessors to customize the some of Spring Security's beans, notably the session consurrency ones (to achive immediate invalidation of a session as soon as a user logs in again, as opposed to Spring's standard behavior of invalidating at the next request).
It's working as expected most of the times, but sometimes when I restart the application it seems like not all beans get modified as I want.
Are SecurityBuilders processed in a specific order or are they instead processed with a ramdom order?
EDIT:
My Config
#EnableWebSecurity
public class SecurityConfig extends AbstractCASWebSecurityConfigurerAdapter {
public SecurityConfig() {
super(true, false, true);
}
#Autowired
private Environment env;
// we need a custom SessionRegistry as there's no way to get ahold of the one created by the configurer.
#Bean
public SessionRegistry sessionRegistry() {
return new SessionRegistryImpl();
}
// we need a custom HttpSessionCsrfTokenRepository as there's no way to get ahold of the one created by the configurer.
#Bean
public CsrfTokenRepository csrfTokenRepository() {
return new HttpSessionCsrfTokenRepository();
}
// our custom ConcurrentSessionControlAuthenticationStrategy that invalidates session immediately
#Bean
public SessionInvalidatingConcurrentSessionControlAuthenticationStrategy myConcurrentSessionControlAuthenticationListener()
{
// we have to recreate the LogoutHandlers because we need to call them
// before invalidating the session
final LogoutHandler [] logoutHandlers = new LogoutHandler [] {
new CookieClearingLogoutHandler("JSESSIONID"),
new CsrfLogoutHandler(csrfTokenRepository())
//, new SecurityContextLogoutHandler() // seems to create problems with redirecting to the same page that caused the login request
};
SessionInvalidatingConcurrentSessionControlAuthenticationStrategy mine = new SessionInvalidatingConcurrentSessionControlAuthenticationStrategy(sessionRegistry(), logoutHandlers);
mine.setExceptionIfMaximumExceeded(false);
mine.setMaximumSessions(1);
return mine;
}
#Override
public void configure(WebSecurity web) throws Exception {
super.configure(web);
boolean devMode = this.env.acceptsProfiles("development");
final String [] ignoredPaths = devMode
? new String [] {"/webjars/**", "/static/**", "/bower_components/**" }
: new String [] {"/webjars/**", "/static/**" };
web
.ignoring()
.antMatchers(ignoredPaths)
.and()
.debug(false)
;
}
protected void configure(final HttpSecurity http) throws Exception {
super.configure(http);
http
.sessionManagement()
.maximumSessions(73467436) // this is just to trigger the ConcurrencyControlConfigurer
.sessionRegistry(sessionRegistry())
.and()
.withObjectPostProcessor(new ObjectPostProcessor<ConcurrentSessionControlAuthenticationStrategy>() {
#SuppressWarnings("unchecked")
#Override
public <O extends ConcurrentSessionControlAuthenticationStrategy> O postProcess(O concurrentSessionControlAS) {
// substitute the ConcurrentSessionControlAuthenticationStrategy created by
// ConcurrencyControlConfigurer with our own
return (O) myConcurrentSessionControlAuthenticationListener();
}
})
.and()
// we need to ignore the stomp endpoint to allow SockJS javascript client to issue POST requests
// to /push/../../.. when using trasports which are not WebSocket;
// at that time, protection is given by Stomp CSRF headers
.csrf()
.csrfTokenRepository(csrfTokenRepository())
.ignoringAntMatchers("/push/**")
.and()
// allow same origin to frame our site to support iframe SockJS
.headers()
.frameOptions().sameOrigin()
.and()
.authorizeRequests()
.antMatchers("/help/**").permitAll() // help redirects do not require authentication
.antMatchers("/push/info").permitAll() // do not require being authenticated for the /info request by SockJS
.anyRequest().authenticated()
.and()
// remove the session cookie when logging out
.logout()
.deleteCookies("JSESSIONID") // see: http://docs.spring.io/autorepo/docs/spring-security/current/reference/htmlsingle/#detecting-timeouts
.and()
;
}
}
AbstractCASWebSecurityConfigurerAdapter is an AbstractWebSecurityConfigurerAdapter that configures CAS.

Categories

Resources