I'm using Java configuration in my Spring MVC application. I need to configure expired-url with java config (not XML config). I found this piece of XML from this answer:
<session-management>
<concurrency-control max-sessions="1" expired-url="/expired" />
</session-management>
But I don't know how can I convert this structure to Java config. I tried this code but it's not working:
#Override
protected void configure(HttpSecurity http) throws Exception {
http.sessionManagement().invalidSessionUrl("/expired")
.and()
...
}
This is how you should do it.
#Override
protected void configure(HttpSecurity http) throws Exception {
http.sessionManagement()
.maximumSessions(1)
.expiredUrl("/expired")
.and()
...
}
Related
I just copied login/register form with spring security from web and i have huge problems. I want make all resources PUBLIC for all, because after 5 hours i totally don't know what is f****** going on with this spring security.
Ok here is my configure method 1:
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
...
...
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
// URLs matching for access rights
.antMatchers("/").permitAll()
.antMatchers("/login").permitAll()
.antMatchers("/register").permitAll()
.antMatchers("/DBDesign").permitAll()
.antMatchers("/index").permitAll()
.antMatchers("/admin/**").hasAuthority("ADMIN")
.antMatchers("/user/**").hasAuthority("USER")
.anyRequest().authenticated()
.and()
// form login
.csrf().disable().formLogin()
.loginPage("/login")
.failureUrl("/login?error=true")
.successHandler(sucessHandler)
.usernameParameter("email")
.passwordParameter("password")
.and()
// logout
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/").and()
.exceptionHandling()
.accessDeniedPage("/access-denied");
}
configuration method 2:
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/resources/**", "/static/**", "/common/**", "/js/**", "/images/**");
}
}
configuration method 3:
#Configuration
public class WebMvcConfig implements WebMvcConfigurer{
#Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry
.addResourceHandler("/webjars/**", "/static/**", "/templates/**")
.addResourceLocations("/webjars/", "classpath:/static/", "classpath:/templates/");
}
}
I am 100% sure that one of these methods is responsible for managing the directories that are to be available before logging in and which are not.
Guys please can someone explain how exactly this work?
Look this is my temporary file structure:
green --- i have access
red --- i dont have access
I can copy and paste path to "green" files and see what is inside, but if i am trying to do the same thing for red files... error 404. How is this possible? Only those 2x dont have permission.
The resourcehandler /static/** points to classpath:/static/
So the security-filter should ignore requests to /sidebar/**, ....
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/sidebar/**","/diagramER/**", .....);
}
Then you can use in your pages something like
<html lang="en">
<head>
....
<script src="/sidebar/js/main.js" ></script>
<script src="/diagramER/DBDesign.js" ></script>
<link rel="stylesheet" type="text/css" href="/sidebar/common/style.css">
</head>
I'm trying to get spring security to allow the serving of static files like .css .js etc. without need to login first.
I've tried creating MVC config with resource handler and changing rules in spring security config, but nothing seems to be working.
MvcConfig.java:
#Configuration
#EnableWebMvc
public class MvcConfig implements WebMvcConfigurer {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/assets/**")
.addResourceLocations("/assets/");
}
}
SecurityConfig.java:
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/", "/assets/**")
.permitAll()
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
#Override
public void configure(WebSecurity web) {
web.ignoring().antMatchers("/assets/**");
}
}
When I go to http://localhost:8080/assets/js/particles.min.js I'm expecting it to return the file contents but every time I try links like localhost:8080/assets/* it returns the content of login.html
My assets files
My project files
Supposing that your static files are under src/main/resources:
There are two main pieces to configure:
Implement the WebMvcConfigurer interface to discover your static resources:
#Configuration
public class MvcConfig implements WebMvcConfigurer {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!registry.hasMappingForPattern("/assets/**")) {
registry.addResourceHandler("/assets/**")
.addResourceLocations("/assets/");
}
}
}
Setup your security configuration to allow static resources (such as CSS, JavaScripts and images) to be publicly accessible:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(securedEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
// Your settings
#Override
protected void configure(HttpSecurity http) throws Exception {
// Your AuthN handlers and filter chain...
http
.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/css/**").permitAll()
.antMatchers("/img/**").permitAll()
.antMatchers("/js/**").permitAll()
.anyRequest().authenticated();
// Logout handler...
}
}
Supposing that you have a CSS file as follows:
src/main/resources/assets/css/layout.css
The web server will make it accessible at:
http://<root_url>:<port>/css/layout.css
Try to change to:
http.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/assets/").permitAll()
.and()
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
web.ignoring().antMatchers("/assets/**");
The statement above will tell spring security to Ignore any request that starts with “/assets/”. So if i were you, i will remove all the following configuration:
.antMatchers("/", "/assets/**")
.permitAll()
fom the configure(HttpSecurity http) method.
I have a simple REST application with authentication service. I tried to add swagger and swagger-ui to it, but I can only see my endpoints in /v2/api-docs.
In swagger-ui.html I see only groups of endpoints but I am unable to extend any list.
In chrome debug I see:
Failed to load resource: the server responded with a status of 401 ()
Uncaught TypeError: Cannot read property 'indexOf' of undefined
and on a terminal with a server:
ERROR 10020 --- [nio-5001-exec-3] c.t.r.a.p.JwtAuthenticationEntryPoint : Responding with unauthorized error. Message - Full authentication is required to access this resource
It looks like my config files are missing something, I tried few solutions I found on a web but still nothing work.
This is my code:
pom
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
controller
#RestController
#PreAuthorize("hasRole('USER')")
#RequestMapping(path = "restaurant")
#Api(value="restaurant", description="Example operations for restaurants")
public class RestaurantController {
// endpoints
}
swagger bean
#Configuration
#EnableSwagger2
public class SwaggerConfig {
#Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage("com.tablebooker.restaurantservice.restaurant"))
.paths(PathSelectors.any())
.build();
}
}
SecurityConfig
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(
securedEnabled = true,
jsr250Enabled = true,
prePostEnabled = true
)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
//other methods
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors()
.and()
.csrf()
.disable()
.exceptionHandling()
.authenticationEntryPoint(unauthorizedHandler)
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/",
"/favicon.ico",
"/**/*.png",
"/**/*.gif",
"/**/*.svg",
"/**/*.jpg",
"/**/*.html",
"/**/*.css",
"/**/*.js")
.permitAll()
.antMatchers("/api/auth/**")
.permitAll()
.antMatchers("/restaurant/**")
.hasRole("USER")
.anyRequest()
.authenticated();
http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/v2/api-docs", "/configuration/ui", "/swagger-resources", "/configuration/security", "/swagger-ui.html", "/webjars/**");
}
}
Any ideas how can I make my configuration work?
For me, there was no issue in traditional Weblogic deployment without any mention of #Override public void configure(WebSecurity web) throws Exception ...Only #Override protected void configure(HttpSecurity http) throws Exception was enough and UI was visible on swagger.
But the same code was not working on Apache Tomcat server so below code was needed ,
#Override public void configure(WebSecurity web) throws Exception { web.ignoring().mvcMatchers(HttpMethod.OPTIONS, "/**"); // ignore swagger web.ignoring().mvcMatchers("/swagger-ui.html/**", "/configuration/**", "/swagger-resources/**", "/v2/api-docs","/webjars/**"); }
/webjars/** being missing in answer by AokoQin.
Answering here because I didn't faced any issues on Weblogic without above code but only Tomcat. I already had resources added via ResourceHandlerRegistry in mvc config.
First you should registry swagger's resources.
#Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/");
}
}
Then cause you're using Spring Security,maybe you should shutdown privileges.
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().mvcMatchers(HttpMethod.OPTIONS, "/**");
// ignore swagger
web.ignoring().mvcMatchers("/swagger-ui.html/**", "/configuration/**", "/swagger-resources/**", "/v2/api-docs");
}
And maybe it's better for you to use swagger which the version is under 2.8.0,or you may have to face to lots of bugs.
The previous answers helped me, but are not quite complete / outdated. I was facing the same issue and it's working now:
#Configuration
public class WebMvcConfiguration extends WebMvcConfigurationSupport {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
}
}
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
...
#Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.mvcMatchers("/swagger-ui.html/**", "/configuration/**", "/swagger-resources/**", "/v2/api-docs", "/webjars/**");
}
...
}
I am using waffle 1.7 + spring 4 + spring security 3.2 + thymeleaf. My problem is, that I am unable to provide custom error page when fall-back form logging fails. This is my configuration:
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/**")
.authenticated()
.and()
.exceptionHandling()
.authenticationEntryPoint(negotiateSecurityFilterEntryPoint())
.accessDeniedPage("/access-denied")
.and()
.addFilterBefore(waffleNegotiateSecurityFilter(),
BasicAuthenticationFilter.class);
}
When user uses browser with SNPENGO off and enters wrong credentials, the default system 500 page appears with following information:
com.sun.jna.platform.win32.Win32Exception: The logon attempt failed. waffle.windows.auth.impl.WindowsAuthProviderImpl.acceptSecurityToken(WindowsAuthProviderImpl.java:134)
waffle.servlet.spi.NegotiateSecurityFilterProvider.doFilter(NegotiateSecurityFilterProvider.java:103) waffle.servlet.spi.SecurityFilterProviderCollection.doFilter(SecurityFilterProviderCollection.java:130)
...
How can I provide my custom page (access-denied.html thymeleaf template) ? So far I have tried everything from http://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc but without success.
Can you try creating a DelegatingNegotiateSecurityFilter and setting an AuthenticationFailureHandler.
Example of DelegatingNegotiateSecurityFilter bean configuration:
<bean id="waffleNegotiateSecurityFilter"
class="waffle.spring.DelegatingNegotiateSecurityFilter"
>
<property name="allowGuestLogin" value="false" />
<property name="Provider" ref="waffleSecurityFilterProviderCollection" />
<property name="authenticationManager" ref="authenticationManager" />
<property name="authenticationSuccessHandler" ref="authenticationSuccessHandler" />
<property name="authenticationFailureHandler" ref="authenticationFailureHandler" />
<property name="accessDeniedHandler" ref="accessDeniedHandler" />
<property name="defaultGrantedAuthority">
<null />
</property>
</bean>
The AuthenticationManager allows for the service provider to authorize the principal.
The authenticationSuccessHandler allows for the service provider to further populate the Authentication object.
The AuthenticationFailureHandler is called if the AuthenticationManager throws an AuthenticationException.
The AccessDeniedHandler is called if the AuthenticationManager throws an AccessDeniedException.
I hope this helps ...
After digging into Spring documentation and tracking what actually waffle does I have been able to solve it in the following "ugly" way. 1. disabling security for /access-denied page to prevent endless redirection loop 2. wrapping waffle filter to catch all exceptions and redirect it
Does anyone have better solution ?
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/access-denied")
.permitAll()
.and()
.authorizeRequests()
.antMatchers("/**")
.authenticated()
.and()
.exceptionHandling()
.authenticationEntryPoint(negotiateSecurityFilterEntryPoint())
.accessDeniedPage("/access-denied")
.and()
.addFilterBefore(waffleNegotiateSecurityFilter(),
BasicAuthenticationFilter.class);
}
public class WaffleWrapperSecurityBean extends GenericFilterBean {
#NotNull
private final GenericFilterBean wrappedFilter;
public WaffleWrapperSecurityBean(GenericFilterBean filter) {
wrappedFilter = filter;
}
#Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
try {
wrappedFilter.doFilter(request, response, chain);
} catch (Exception e) {
((HttpServletResponse) response)
.sendRedirect("access-denied?message="
+ e.getLocalizedMessage());
}
}
#Override
public void destroy() {
wrappedFilter.destroy();
}
}
// controller code ommited
It looks like some filter not added.
I use Spring security 3.2.0.RELEASE with java-config.
Full project posted on GitHub
SecurityConfig.java is here: SecurityConfig.java
I try to set up filter in:
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/app/**").hasRole("ADMIN")
.and()
.formLogin()
.loginPage("/")
.defaultSuccessUrl("/app/")
.failureUrl("/?error=1")
.permitAll()
.and()
.logout()
.logoutSuccessUrl("/?logout");
}
After csrf().disable() - But problem not solved...
Help me please to solve this problem for I can use /j_spring_security_check with my own CustomUserDetailsService!
I have no experience with Spring Security Java Config, but I checked your code and the API and it seems that setting login processing URL will let you login:
AbstractAuthenticationFilterConfigurer.loginProcessingUrl("/j_spring_security_check")
So your code should be:
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/app/**").hasRole("ADMIN")
.and()
.formLogin()
.loginProcessingUrl("/j_spring_security_check")
.loginPage("/")
.defaultSuccessUrl("/app/")
.failureUrl("/?error=1")
.permitAll()
.and()
.logout()
.logoutSuccessUrl("/?logout");
}
I would expect this is set by default.
In addition, to make use of MyCustomUserDetailsService, instead of autowiring it as it is now (Proxy created by Spring), I would configure it manually:
public class MyCustomUserDetailsService implements UserDetailsService {
private UserDAO userDAO;
public MyCustomUserDetailsService(UserDAO userDAO) {
this.userDAO = userDAO;
}
// ...
}
Notice, no #Service/#Component annotations and DAO injected via Ctor. In security config:
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private DataSource dataSource;
#Autowired
private UserDAO userDAO;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication()
.dataSource(dataSource)
.and()
.userDetailsService(new MyCustomUserDetailsService(userDAO));
}
// ...
}
Now I am sure, the UserDetailService is properly configured. And for sure it will be used while logging in in the application.
I also noticed that the username and password is not used. This is because in login.jsp you use j_username and j_password whereas username parameter should be username and password parameter should be password.
<input type="text" id="username" class="span4" name="username" placeholder="Username" />
<input type="password" id="password" class="span4" name="password" placeholder="Password" />
Look at the FormLoginConfigurer class.