how to perform operation just before logout in spring? - java

First of all this is not a duplicate question i checked answers here! and
here! but couldnt get it to work.
Also i want to perform it just before logout so can not use logoutSuccessHandler.
So i need to create a custom LOGOUT_FILTER , with which i am really having hard time getting it to work.
here is my spring-security xml in which i tried two methods
first was :-
<custom-filter ref="logoutFilter" position="LOGOUT_FILTER" />
<beans:bean id="logoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
<beans:constructor-arg index="0" value="/logoutSuccess" />
<beans:constructor-arg index="1">
<beans:list>
<beans:bean id="securityContextLogoutHandler"
class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler" />
<beans:bean id="myLogoutHandler" class="com.fe.cms.listener.SimpleLogoutHandler" />
</beans:list>
</beans:constructor-arg>
<beans:property name="filterProcessesUrl" value="/logout" />
</beans:bean>
but this gives me error
Configuration problem: Security namespace does not support decoration of element [custom-filter]
then i tried..
<beans:bean id="logoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
<beans:constructor-arg index="0" value="/logout" />
<beans:constructor-arg index="1">
<beans:ref bean="securityContextLogoutHandler" />
<beans:ref bean="myLogoutHandler" />
</beans:constructor-arg>
<beans:property name="filterProcessesUrl" value="/logout" />
</beans:bean>
<beans:bean id="securityContextLogoutHandler"
class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler" />
<beans:bean id="myLogoutHandler" class="com.fe.cms.listener.SimpleLogoutHandler" />
<http auto-config="false" entry-point-ref="authenticationManger">
<custom-filter ref="logoutFilter" position="LOGOUT_FILTER" />
</http>
but this gives me error :-
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.filterChains': Cannot resolve reference to bean 'org.springframework.security.web.DefaultSecurityFilterChain#48' while setting bean property 'sourceList' with key [48]; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.web.DefaultSecurityFilterChain#48': Cannot create inner bean '(inner bean)' of type [org.springframework.security.web.access.ExceptionTranslationFilter] while setting constructor argument with key [6]; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)#181': Could not resolve matching constructor (hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)
Please can anyone tell where am i doing wrong ..
i will post full xml files if needed

According to your clarification what you want is to get access the to session and perform some logic. Instead of hacking around with a custom LogoutFilter simply write an ApplicationListener that listens to HttpSessionDestroyedEvents.
#Component
public class SessionListener implements ApplicationListener<HttpSessionDestroyedEvent> {
public void onApplicationEvent(HttpSessionDestroyedEvent evt) {
HttpSession session = evt.getSession();
// Your logic here
}
}
To be able re receive events make sure that you register the HttpSessionEventPublisher in your web.xml.
<listener>
<listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>
Main advantage of this solution is that you will also be able to process sessions that timeout and not only regular logouts.

If you need to execute some operation just before logout I suppose Spring interceptors can help you.
You could implement a class like this:
public class JustBeforeLogoutInterceptor extends HandlerInterceptorAdapter {
#Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
boolean res = super.preHandle(request, response, handler);
//
// your code...
//
return res;
}
}
Then you need to configure the interceptor:
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/logout" />
<bean class="your.app.JustBeforeLogoutInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
This should work. Take a try.

You can try to extend current LogoutFilter and execute your custom logic before calling super class' doFilter method.
Like this
public class CustomLogoutFilter extends LogoutFilter {
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
if (requiresLogout(request, response)) {
// IMPLEMENT YOUR CUSTOM LOGIC HERE
super.doFilter(req, res, chain);
return;
}
chain.doFilter(request, response);
}
}
Then you have to replace default LogoutFilter with your CustomLogoutFilter
<http>
<custom-filter position="LOGOUT_FILTER" ref="customLogoutFilter" />
</http>
<bean id="customLogutFilter" class="example.CustomLogoutFilter">
<property name="filterProcessesUrl" value="/logout" />
<!-- Put other needed properties here-->
</bean>

Related

Spring Security Custom Filter Never Called

The problem is that my custom Spring Security filter is never invoked when a request comes in. During debugging, I found that in doFilter() in FilterChainProxy, my filter (JwtAuthenticationFilter) can be fetched:
But it's skipped. Then I found it's due to:
So the superclass of my filer, which is AbstractAuthenticationProcessingFilter thinks the request doesn't need authentication and it just calls doFilter() to pass it down. I think my configs specified that auth is needed. This specific request is /ui/home/index.jsp, where \ui is the context.
My security configs:
<http use-expressions="true" pattern="/**" entry-point-ref="JwtAuthenticationEntryPoint" create-session="stateless">
<custom-filter before="CONCURRENT_SESSION_FILTER" ref="jwtAuthenticationFilter" />
<intercept-url pattern="/home/**" access="isAuthenticated()"/>
// some other intercept-url definitions
</http>
<authentication-manager alias="authenticationManager">
<authentication-provider ref="authenticationProvider"/>
</authentication-manager>
And bean configs:
<bean id="jwtAuthenticationFilter" class="com.pk.jjwt.JwtAuthenticationTokenFilter" >
<property name="authenticationManager" ref="authenticationManager"/>
<property name="authenticationSuccessHandler" ref="jwtAuthenticationSuccessHandler" />
</bean>
<bean id="JwtAuthenticationEntryPoint" class="com.pk.jjwt.JwtAuthenticationEntryPoint" />
<bean id="authenticationProvider" class="com.pk.jjwt.JwtAuthenticationProvider" />
<bean id="jwtAuthenticationSuccessHandler" class="com.pk.jjwt.JwtAuthenticationSuccessHandler" />
I wonder what might cause the filters getting skipped? I think I specified that every url pattern needs to be authenticated. I'm not sure why it thinks that request doesn't need authentication from my custom filter.
Edit:
So I debugged the requiresAuthentication() method, and found:
Basically it's evaluating uri.endsWith("/ui/**") and uri is /ui/home/index.jsp. It returned false, so the filter is skipped.

Spring WebMVC - How to wire an interceptor for EULA check after successful login?

I'm using Spring MVC and Security to authenticate my web service.
I want the system to check that any newly authenticated users have accepted the EULA. If EULA check is good then let them continue on their merry ways.
If EULA check fails then have them stop by the "/eula" page until they accept.
I have the following class:
#Component
public class AssertEulaInterceptor extends HandlerInterceptorAdapter {
#Value("eulaCookieName")
private String cookieName;
#javax.annotation.Resource(name = "EULAResource")
private Resource eulaResource;
#Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("EULA CHECK");
Cookie cookie = extractCookie(cookieName, request.getCookies());
if (assertEulaAccepted(request, response, handler, cookie)) {
response.sendRedirect("/services/eula");
}
}
}
and in my servlet-context.xml file:
...
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/static/j_spring_security_check*" />
<bean class="com.example.AssertEulaInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
...
I have also tried:
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/static/j_spring_security_check*" />
<mvc:exclude-mapping path="/login*"/>
<mvc:exclude-mapping path="/eula*"/>
<bean class="com.example.AssertEulaInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
But this doesn't do the check. ("EULA CHECK" never appears in console output.)
Thanks.
Use exclude-mapping
<mvc:interceptor>
<mvc:mapping path="/check-me-pattern"/>
<mvc:exclude-mapping path="/exclude-me-pattern"/>
<bean class="com.example.MyInterceptor"/>
</mvc:interceptor>

GWT RPC with Spring role-base Security

My question is quite simple "Can have any problems when using Spring security and GWT RPC ?" .
I would like to use spring's method level security on GWT's RPC methods.For instance : at my ServiceImpl class , I used Expression-Based Access Control as below.
#PreAuthorize("hasRole('ROLE_ADMIN')")
public final String getById(Long id) {
.........
}
If un-authorize role access users trying to access page dealing with this rpc method , exception was thrown and don't redirect to my access-denied page. I have no idea why doesn't go to my access-denied page ? I got an exception at my console as
threw an unexpected exception: org.springframework.security.access.AccessDeniedException: Access is denied
I configured as this answer exactly but still getting above error.Please correct me if I am wrong "I think this problem may due to gwt's RPC" because non-rpc methods were fine and redirect to my unSecure.html . I spend about 3 days for this error . At onFailure(Throwable caught) of my asynchronous method show
500 The call failed on the server; see server log for details
I want to show my configurations .
spring-security.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns:sec="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd">
<sec:global-method-security
secured-annotations="enabled" pre-post-annotations="enabled" />
<sec:http auto-config="false" entry-point-ref="authenticateFilterEntryPoint">
<sec:access-denied-handler ref="accessDeniedHandler" />
<sec:intercept-url pattern="/login.html" />
<sec:logout logout-url="/logout.html" logout-success-url="/login.html"
invalidate-session="true" />
<sec:form-login login-page="/login.html"
login-processing-url="/login_check" authentication-failure-url="/login.html?error=1" />
<sec:session-management invalid-session-url="/login.html">
<sec:concurrency-control max-sessions="50"
error-if-maximum-exceeded="true" />
</sec:session-management>
<sec:remember-me key="mykey"
token-validity-seconds="604800" />
</sec:http>
<beans:bean id="authenticateFilterEntryPoint"
class="mypackage.common.security.SessionTimeoutEntryPoint">
<beans:property name="loginFormUrl" value="/login.html" />
</beans:bean>
<beans:bean id="accessDeniedHandler"
class="mypackage.common.security.AccessDeniedEntryPoint">
<beans:property name="errorPage" value="/unSecure.html" />
</beans:bean>
<beans:bean
class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<beans:property name="defaultErrorView" value="uncaughtException" />
<beans:property name="excludedExceptions"
value="org.springframework.security.access.AccessDeniedException" />
<beans:property name="exceptionMappings">
<beans:props>
<beans:prop key=".DataAccessException">dataAccessFailure</beans:prop>
<beans:prop key=".NoSuchRequestHandlingMethodException">resourceNotFound</beans:prop>
<beans:prop key=".TypeMismatchException">resourceNotFound</beans:prop>
<beans:prop key=".MissingServletRequestParameterException">resourceNotFound</beans:prop>
</beans:props>
</beans:property>
</beans:bean>
<beans:bean id="authenticationUserService"
class="mypackage.common.security.AuthenticationUserService" />
<sec:authentication-manager>
<sec:authentication-provider
user-service-ref="authenticationUserService">
<sec:password-encoder hash="md5" />
</sec:authentication-provider>
</sec:authentication-manager>
<beans:bean id="authLoggerListener"
class="org.springframework.security.authentication.event.LoggerListener" />
<beans:bean id="eventLoggerListener"
class="org.springframework.security.access.event.LoggerListener" />
AccessDeniedEntryPoint.java
public class AccessDeniedEntryPoint extends org.springframework.security.web.access.AccessDeniedHandlerImpl {
private static final Logger logger = LoggerFactory.getLogger(AccessDeniedEntryPoint.class);
#Override
public void handle(HttpServletRequest request, HttpServletResponse response,
AccessDeniedException accessDeniedException) throws IOException, ServletException {
super.handle(request, response, accessDeniedException);
}
}
SessionTimeoutEntryPoint.java
public class SessionTimeoutEntryPoint extends LoginUrlAuthenticationEntryPoint {
#Override
public final void commence(final HttpServletRequest request, final HttpServletResponse response,
final AuthenticationException authException) throws IOException, ServletException {
super.commence(request, response, authException);
}
}
So , I would like to get unSecure.html when un-authorize role users access this method. I would really appreciated any of your suggestions. Sorry for my long question. I don't want to hit my head anymore ! Thanks.
As in my last response, I used this long time ago. In my case instead of dealing always with urls I delegated into handlers.
I mean, if you want to integrate GWT-RPC with Spring-Security, the first thing that I did, was from my GWT app try to login against Spring.
So the first thing that you need to do is create a RPC-CALL (here official documentation) for login.
I found useful the annotation #RemoteServiceRelativePath("examplelogin.rpc"), so if you use it you can take advantage about the path, and then, in the spring-security.xml you can filter the request by those path (see the updated example below).
Not sure why you want to integrate GWT-RPC with Spring-Security and then you specify /login.html (should it be a rpc call, described befored instead of html? But maybe you are using your own MVP with GWT, so I am not saying that is wrong, only it surprises me :) ).
Reading your code I do not see something wrong, but in my case I have some differences:
....
<http use-expressions="true" entry-point-ref="http401UnauthorizedEntryPoint">
<intercept-url pattern="/yourProject/public.rpc" access="permitAll" />
<intercept-url pattern="/yourProject/examplelogin.rpc" access="hasRole('ROLE_ADMIN')" />
<form-login authentication-success-handler-ref="authenticationSuccessHandler"
authentication-failure-handler-ref="authenticationFailureHandler"/>
..... //logout, session-management, custom-filters....
<beans:bean id="http401UnauthorizedEntryPoint"
class="your.project.Http401UnauthorizedEntryPoint" />
<beans:bean id="authenticationSuccessHandler"
class="your.project.GWTAuthenticationSuccessHandler"/>
<beans:bean id="authenticationFailureHandler"
class="your.project.GWTAuthenticationFailureHandler"/>
</http>
....
You asked specifically about the possibility of using Spring-Security with GWT-RPC (that is the reason because in the <intercept-url> tags I place there the .rpc urls)
Note that the
The answer is yes, I have done it (three years ago, but I did :) )
I think here the keys for your problem are:
Specify the interceptor url for the RPC calls or your /login.html
Delegate on handlers like I did (be careful maybe you are doing well
and the error is in other part, but at least I did like in the example and it
worked).
Sorry for not showing you directly the error, I hope this answers will help.
Thanks.

Spring Security authentication manager won't get picked up on custom filter

I'm trying to create a custom filter to take care of authentication, since I'm forced to use a combination of an AD and local database (arg!) to determine access rights. I'm using the official docs, for this particular issue mostly this part.
However, when I run my server it is complaining about the AuthenticationManager being null, while I believe I am setting it in XML as covered in this SO question. What am I missing here?
The exception:
SEVERE: Context initialization failed org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myUsernamePasswordAuthenticationFilter' defined in file [*snip*]:
Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: authenticationManager must be specified
...
Caused by: java.lang.IllegalArgumentException: authenticationManager must be specified
at org.springframework.util.Assert.notNull(Assert.java:112)
The XML: (with some simplified class names)
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:sec="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<context:property-placeholder location="classpath*:META-INF/spring/*.properties" />
<context:spring-configured />
<context:component-scan base-package="myapp" />
<!-- Spring Security Configuration. -->
<sec:http auto-config="false" entry-point-ref="loginUrlAuthenticationEntryPoint"
access-denied-page="/denied.jsp">
<sec:custom-filter position="FORM_LOGIN_FILTER" ref="myAuthenticationFilter" />
<sec:intercept-url pattern="/login" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<sec:intercept-url pattern="/404.jsp" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<sec:intercept-url pattern="/index.jsp" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<sec:intercept-url pattern="/**" access="ROLE_USER" />
<sec:logout logout-url="/logout" logout-success-url="/login" />
</sec:http>
<sec:authentication-manager alias="authenticationManager">
<sec:authentication-provider ref="myAuthenticationProvider" />
</sec:authentication-manager>
<bean id="loginUrlAuthenticationEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<property name="loginFormUrl" value="/login" />
</bean>
<bean id="myAuthenticationFilter" class="myapp.MyUsernamePasswordAuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager" />
</bean>
<bean id="myAuthenticationProvider" class="myapp.MyAuthenticationProvider" />
The Filter:
#Component
public class MyUsernamePasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
public AdminUsernamePasswordAuthenticationFilter() {
super("/login");
}
#Override
public Authentication attemptAuthentication(final HttpServletRequest request,
final HttpServletResponse response) throws AuthenticationException {
// stuff and:
return getAuthenticationManager().authenticate(new UsernamePasswordAuthenticationToken(
login, request.getParameter("password")));
}
}
The AuthenticationProvider:
#Component
public class MyAuthenticationProvider implements AuthenticationProvider {
#Override
public Authentication authenticate(final Authentication authentication) throws AuthenticationException {
// all the funky AD+DB code
return null;
}
#Override
public boolean supports(final Class<?> clazz) {
return true;
}
}
I am running Java 6, the latest Spring Security (3.1.4.RELEASE) and Spring (3.2.3.RELEASE) versions, running on a Tomcat v6 server. Different Spring versions do not appear to be a problem (related SO question). And if it would be a problem, having to run Spring 3.1.4 if you want to use Spring Security is just meh...
Some additional things I tried to no avail:
I tried ditching the <sec:authentication-manager /> in favour of a normal bean, as mentioned here (bottom answer).
I tried adding bean id's, names, authentication-manager-refs in all sorts of combinations.
Ah... I spot the basic error made by many in Spring. You have your bean MyUsernamePasswordAuthenticationFilter defined in XML, which is correct. However you have it also annotated by #Component annotation, which means it is being picked and registered as another bean definition by component scan. And bean instance comming from this definition won't indeed have its authenticationManager dependency initalized.
Just remove the #Component annotation in MyUsernamePasswordAuthenticationFilter and you should be OK.

Spring security not hitting default-target-url after successful authtication

I have implemented spring-security in my application, my spring-security.xml has following form-login tag.
<form-login login-page="/login.htm" default-target-url="/dashboard.htm"
authentication-failure-url="/login.htm?error=true"
authentication-success-handler-ref="authenticationSuccessHandler" />
I want to login from /login.htm and after successful authetication I want user to hit dashboard.htm. Everythig is working fine except for the fact that after successfull authetication it doesn't hit /dashboard.htm but hits the context..but if I manually type dashboard.htm in url then everything works fine...Yes..I have the implementation of authticationSuccessHandler.
Try removing the default-target-url attribute and add the following:
<b:bean id="authenticationSuccessHandler" class="com.example.CustomSimpleURLAuthenticationSuccessHandler">
<b:property name="defaultTargetUrl" value="/dashboard.htm"/>
</b:bean>
<beans:bean id="loginSuccessHandler" class="com.example.LoginSuccessHandler">
<beans:property name="defaultTargetUrl" value="/security/success"/>
<beans:property name="alwaysUseDefaultTargetUrl" value="true"/>
</beans:bean>
public class LoginSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
#Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws ServletException, IOException {
request.getSession().setMaxInactiveInterval(60 * 60); //one hour
System.out.println("Session set up for 60min");
super.onAuthenticationSuccess(request, response, authentication);
}
}
I use this suggestion from the question spring is not redirecting to default target url?. I tried this and it is working.
<form-login login-page="/login.htm"
default-target-url="/dashboard.htm"
always-use-default-target="true"/>
As you can see in the image, there is some kind of bad design (IMO It always redirect to the default-target-url).
When you go to the login form from a forbidden resource, it will redirect you to that URL and not going thru the default-target-url
http://i.stack.imgur.com/fj9ou.png

Categories

Resources