waffle custom error page in spring - java

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

Related

Convert Spring xml configuration to Java configuration under Spring Boot

I am trying to migrate existing application Spring security configuration written in XML to Java Configuration (with Spring Boot)
Can you please help as to how the Java config needs to be defined for the below xml. I keep getting confused looking at different webpages..
Thanks in advance!
<security:http auto-config="false" entry-point-ref="filterEntryPoint">
<security:custom-filter before="FORM_LOGIN_FILTER" ref="myWebAuthorizationFilter" />
<security:intercept-url pattern="/**" access="ROLE_USER,ROLE_EVP"/>
</security:http>
<bean id="filterEntryPoint"
class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<property name="loginFormUrl">
<value>https://companyLogin.com</value>
</property>
<property name="forceHttps">
<value>false</value>
</property>
</bean>
For this part, you will need to define a custom filter
<security:http auto-config="false" entry-point-ref="filterEntryPoint">
<security:custom-filter before="FORM_LOGIN_FILTER" ref="myWebAuthorizationFilter" />
<security:intercept-url pattern="/**" access="ROLE_USER,ROLE_EVP"/>
</security:http>
such as
public class MyCustomFilter extends GenericFilterBean {
#Override
public void doFilter (ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
chain.doFilter(request, response);
}
And then register the custom filter
#Configuration
public class CustomWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.addFilterBefore(new MyCustomFilter(), UsernamePasswordAuthenticationFilter.class);
.authorizeRequests()
.antMatchers("/**").access("hasRole('ROLE_USER') and hasRole('ROLE_EVP')");
}
}
To learn more about custom filter click here.
Next, for this one
<bean id="filterEntryPoint"
class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<property name="loginFormUrl">
<value>https://companyLogin.com</value>
</property>
<property name="forceHttps">
<value>false</value>
</property>
You need to define a bean
#Configuration
public class CustomWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.addFilterBefore(new MyCustomFilter(), UsernamePasswordAuthenticationFilter.class);
.authorizeRequests()
.antMatchers("/**").access("hasRole('ROLE_USER') and hasRole('ROLE_EVP')");
//defined bean
#Bean
public LoginUrlAuthenticationEntryPoint filterEntryPoint() {
LoginUrlAuthenticationEntryPoint entryPoint = new LoginUrlAuthenticationEntryPoint("https://companyLogin.com");
entryPoint.setForceHttps(false);
return entryPoint;
}
}
I think that's all.

spring security set expired-url

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()
...
}

How to setup https acces to the specific path in Spring

I'm completely new to Spring and MVC. I'm trying to setup https access to the specific section of my application.
I have 2 buttons: admin and user. When I press admin button, I should input login and password to enter the administration section. When I click on user button I want to pass in https zone and to get certificate from user. And I need all paths user/** to have https.
Here is my code
startPage.jsp
Admin
User
UserController.java
#RequestMapping(value = "/user", method = RequestMethod.GET)
public ModelAndView userArea(Model model, HttpServletRequest request, HttpServletResponse response) throws Exception {
ModelAndView mv = new ModelAndView();
if (getCertificate(request) != null) {
mv.setViewName("UserArea");
} else {
mv.setViewName("error");
}
return mv;
}
SecurityConfig.java
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf()
.disable()
.authorizeRequests()
.antMatchers("/admin/**").access("hasRole('ADMIN_ROLE')")
.antMatchers("/user/**").permitAll()
.antMatchers("/**").permitAll()
.anyRequest().authenticated();
http.formLogin()
.loginPage("/login")
.loginProcessingUrl("/j_spring_security_check")
.failureUrl("/login?error")
.usernameParameter("j_username")
.passwordParameter("j_password")
.permitAll();
http.logout()
.permitAll()
.logoutUrl("/logout")
.logoutSuccessUrl("/login?logout")
.invalidateHttpSession(true);
}
...
}
I know that now path users/** is using permitAll(), but help me, please, setup https access to this path or give me please some advice where to read some articles. And one more question, when I want to get client certificate, it contains in HttpServletRequest argument of userArea method, am I right?
This can be done using spring security as shown below.
<security:intercept-url pattern="/reports" access="ROLE_ADMIN" requires-channel="https"/>
<security:intercept-url pattern="/login" access="IS_AUTHENTICATED_ANONYMOUSLY" requires-channel="https"/>
<security:intercept-url pattern="/**" access="ROLE_USER" requires-channel="https"/>
Below blog will give more info
http://myshittycode.com/2014/06/12/spring-security-forcing-urls-to-use-https/l

/j_spring_security_check HTTP error 404

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.

Moving Spring Security To Java Config, where does authentication-success-handler-ref go?

Our app has a custom success handler for successful logins. It basically redirects them to the page they were on when their session expired.
We're moving to a Java config rather than a spring xml config. The rest of the config went very smoothly, but we can't find where to put the authentication-success-handler-ref attribute of the security:form-login tag.
<security:http auto-config='true'>
...
<security:intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY"/>
<security:form-login login-page="/login" default-target-url="/sites"
authentication-failure-url="/login"
authentication-success-handler-ref="authenticationSuccessHandler"/>
...
Here's our config, so far.
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.failureUrl("/login")
.and()
.logout()
.permitAll()
.and()
}
Also, we can't find where to put default-target-url, but that is definitely less important.
Caveat, we're actually using Groovy, but the code is basically the same as a Java config.
All settings can be done inside the global configure method. Add the following:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/sites")
.failureUrl("/login")
.successHandler(yourSuccessHandlerBean) // autowired or defined below
.and()
.logout()
.permitAll()
.and()
}
You have to create bean extending SimpleUrlAuthenticationSuccessHandler or SavedRequestAwareAuthenticationSuccessHandler. For example:
#Bean
public SavedRequestAwareAuthenticationSuccessHandler successHandler() {
SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
successHandler.setTargetUrlParameter("/secure/");
return successHandler;
}
Then you have to setup it on bean extending AbstractAuthenticationProcessingFilter:
UsernamePasswordAuthenticationFilter authenticationFilter = new UsernamePasswordAuthenticationFilter();
authenticationFilter.setAuthenticationSuccessHandler(successHandler());

Categories