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
Related
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>
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>
I'm trying to implement a Rest web service with Jersey, Spring and Spring security (3.2.5).
I want the server to require the basic auth header for the request to the rest web service. If authentication succeeds, then jersey should handle the request. If it fails, I want to return an empty response with the status 403.
Currently my configuration is the following:
<bean id="myAuthenticationEntryPoint"
class="de.tuberlin.snet.baroudeur.Authentication.EntryPoint" />
<!-- HTTP basic authentication in Spring Security -->
<security:http create-session="stateless" auto-config="false"
disable-url-rewriting="true" entry-point-ref="myAuthenticationEntryPoint">
<security:intercept-url pattern="**" access="ROLE_USER" />
<security:http-basic />
</security:http>
<security:authentication-manager>
<security:authentication-provider>
<security:user-service>
<security:user name="username" password="password"
authorities="ROLE_USER" />
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
and my EntryPoint:
public class EntryPoint extends BasicAuthenticationEntryPoint {
public void commence(ServletRequest request, ServletResponse response,
AuthenticationException authException) throws IOException,
ServletException {
HttpServletResponse httpResponse = (HttpServletResponse) response;
httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN);
}
}
I tried a lot of things, like custom AuthenticationFailureHandler, or custom EntryPoint but nothing has worked so far.
Thanks
Edit:
My current solution only returns a 401 response with the basic tomcat templates and the browser asks for the user credentials.
When using the debugging mode, it seems that the commence() method of my custom entry point is never called, why is that?
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.
I was using a tutorial on this link:
http://www.mkyong.com/spring-security/display-custom-error-message-in-spring-security/
To show a custom error message on login form and I got it at the beginning. But after declaring a authentication-failure-handler-ref="myAuthErrorHandler" for a custom failure authenticator handler I can't see it the custom message on the login form:
What I am doing wrong? Can anybody explain me what happen and why the 'Invalid username or password' doesn't show?
Here's the code:
AuthentificationListener
public class AuthentificationListener implements AuthenticationFailureHandler {
#Override
public void onAuthenticationFailure(HttpServletRequest request,
HttpServletResponse response, AuthenticationException ae)
throws IOException, ServletException {
UsernamePasswordAuthenticationToken user = (UsernamePasswordAuthenticationToken) ae
.getAuthentication();
/* User */
response.sendRedirect(request.getContextPath()
+ "/abc/main/loginfailed");
}
}
applicationContext.xml:
<bean id="myAuthErrorHandler" class="org.abc.handler.AuthentificationListener"/>
Spring Security:
<http auto-config="true">
<intercept-url pattern="/abc/main/welcome*" access="ROLE_USER" />
<intercept-url pattern="/abc/main/record/**" access="ROLE_USER" />
<form-login
login-page="/abc/main/login"
authentication-failure-handler-ref="myAuthErrorHandler"
default-target-url="/abc/main/welcome"
/>
<logout logout-success-url="/abc/main/logout" />
</http>
login.jsp:
<c:if test="${not empty error}">
<div class="errorblock">
Your login attempt was not successful, try again.<br /> Caused :
${sessionScope["SPRING_SECURITY_LAST_EXCEPTION"].message}
</div>
</c:if>
LoginController.java:
#RequestMapping(value="/loginfailed", method = RequestMethod.GET)
public String loginerror(ModelMap model) {
model.addAttribute("error", "true");
return "login";
}
Update: To answer on Mani answer, I'm using a LoginController, which redirects loginfailed requests to login.jsp and is sending an 'error' attribute with the 'true' value. The problem is I can't see the message on the login.jsp using this expression:
${sessionScope["SPRING_SECURITY_LAST_EXCEPTION"].message}
Any Idea? Thank You very much!
On Failure of Authendication, you have asked to redirect to different Page.
response.sendRedirect(request.getContextPath()
+ "/abc/main/loginfailed");
your loginfailed jsp not displayed ? it doesn't has div like errorblock in login page ? are you seeing different error in loginfailed.jsp ?
EDIT:
Ok I got it . Before authentication-failure-handler-ref="myAuthErrorHandler" Spring Handles the failure case and placed message in Session with the key SPRING_SECURITY_LAST_EXCEPTION .
After adding the failure handler i.e
authentication-failure-handler-ref="myAuthErrorHandler"
You have to handle the error. You can set the message in session. or simply call the super.onAuthenticationFailure . Your handler is not doing anything !!!
<div style="color: red">
Your login attempt was not successful, try again.<br /> Caused :
${sessionScope["SPRING_SECURITY_LAST_EXCEPTION"].message}
</div>
use this, remove form login.jsp
create a properties file name as
mymessages.properties
AbstractUserDetailsAuthenticationProvider.badCredentials=Invalid username or password
and save it and place into your project classpath
and add the the bean in your spring-contex.xml
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames">
<list>
<value>mymessages</value>
</list>
</property>
</bean>