We upgraded an application from Spring 3 to Spring 5 and now no matter what we do we get response 302 upon login.
I access /login.jsp and fill in username and password, and then click "Log in" to submit the form.
In Tomcat logs I see that the reponse status code is 302.
"POST /login HTTP/1.1" 302 -
security.xml
<global-method-security secured-annotations="enabled" />
<http auto-config='true' use-expressions="true">
<access-denied-handler error-page="/error403.jsp"/>
<intercept-url pattern="/css/**" access="permitAll" />
<intercept-url pattern="/js/**" access="permitAll" />
<intercept-url pattern="/images/**" access="permitAll" />
<intercept-url pattern="/login.jsp" access="permitAll" />
<intercept-url pattern="/reset-password/**" access="permitAll" />
<intercept-url pattern="/checkAuth.tok*" access="permitAll" />
<intercept-url pattern="/activationStatus.tok*" access="permitAll" />
<intercept-url pattern="/renewAuth.tok*" access="permitAll" />
<intercept-url pattern="/reset-password*" access="permitAll" />
<intercept-url pattern="/reset-password/*" access="permitAll" />
<intercept-url pattern="/login" access="permitAll"/>
<intercept-url pattern="/**" access="isAuthenticated()"/>
<form-login authentication-success-handler-ref="refererHandler"
login-processing-url="/login"
login-page="/login.jsp" default-target-url="/firms-log-event"
authentication-failure-url="/login.jsp?error=true"/>
<logout logout-url="/logout" logout-success-url="/login.jsp" />
<anonymous username="guest" granted-authority="ROLE_ANONYMOUS" />
<csrf disabled="true"/>
<remember-me />
</http>
<beans:bean
class="portal.web.security.RefererRedirectionAuthenticationSuccessHandler"
name="refererHandler"/>
login.jsp:
<form id="login" action="<c:url value="/login" />"
method="post" onsubmit="DoSubmit();" name="login-form">
<fieldset>
<legend>Please enter your login credentials:</legend>
<c:if test="${not empty param.error}">
<div class="error">
${sessionScope["SPRING_SECURITY_LAST_EXCEPTION"].message}</div>
</c:if>
<ol>
<li><label for="user-id">user-id</label> <input id="user-id"
class="inputbox" type="text"
maxlength="<%=String.valueOf(ValidatorUtil.MAX_NAMES_SIZE)%>"
name="username" /> <input id="user-real-id" class="inputbox"
type="hidden"
maxlength="<%=String.valueOf(ValidatorUtil.MAX_NAMES_SIZE)%>"
name="j_username" /></li>
<li><label for="password">password</label> <input
id="password" class="inputbox" type="password"
maxlength="<%=String.valueOf(ValidatorUtil.MAX_NAMES_SIZE)%>"
name="j_password" /></li>
<li><label for="firmAdmin">firm admin</label> <input
id="firmAdmin" type="checkbox" checked="checked"></li>
<li><input class="submit greybutton" type="submit"
value="Submit" name="Submit"></li>
<li>
<p class="forgot-pass">
forgot your password? <a href="/reset-password">reset
password.</a>
</p>
</li>
</ol>
</fieldset>
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
</form>
RefererRedirectionAuthenticationSuccessHandler.java:
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
/**
*
*/
public class RefererRedirectionAuthenticationSuccessHandler
extends SimpleUrlAuthenticationSuccessHandler
{
/**
*
*/
public RefererRedirectionAuthenticationSuccessHandler()
{
super();
setUseReferer(true);
}
}
We must be missing something and any help would be highly appreciated
Related
I'm trying to learn spring security, so I've downloaded some sample project and then I tried to implement that solution to my project.But when I try to submit login form, I always get 403 page which is defined in applicationContext-security.xml. But I expected is 'authentication-failure-url' for invalid username/pwd, or 'default-target-url' for correct username/pwd rather than 'access-denied-handler' /forbidden(my 403 page). I'd be really thankful, if somebody, who is more experienced, could help me.
application-Security.xml
<security:http security="none" pattern="/public/**"/>
<security:http security="none" pattern="/login*"/>
<security:http security="none" pattern="/maxSessionError*"/>
<security:http security="none" pattern="/forbidden*"/>
<security:http use-expressions="true">
<security:intercept-url pattern="/**" access="isAuthenticated()"/>
<security:form-login login-page="/login"
default-target-url="/home"
authentication-failure-url="/login"
authentication-success-handler-ref="loginSuccessHandler"
/>
<security:logout invalidate-session="true" delete-cookies="true" success-handler-ref="logoutSuccessHandler" />
<security:access-denied-handler error-page="/forbidden"/>
<security:session-management session-fixation-protection="newSession" >
<security:concurrency-control max-sessions="1" error-if-maximum-exceeded="false" expired-url="/maxSessionError" />
</security:session-management>
<security:custom-filter ref="xunxiSecurityInterceptor" before="FILTER_SECURITY_INTERCEPTOR" />
</security:http>
login.jsp
<form action="<%=request.getContextPath()%>/j_spring_security_check" method="post" class="login-form" id="login-form" >
<label>Username</label>
<input type="text" placeholder="username" name="j_username"/>
<label>Password</label>
<input type="password" placeholder="password" name="j_password"/>
<label>
<input type="checkbox" name="_spring_security_remember_me" /> Remember me </label>
<button type="submit" >
Login
</button>
</div>
</form>
You write your Spring Security version is 4.0.2 but your JSP seems to be written for Spring Security 3. Migrate your JSP:
Change login processing URL (form action) to /login.
Change input names to username and password.
Add input element for CSRF protection: <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>. CSRF protection is enabled by default from Spring Security 4.
What i have to do to not require login on the main page?
this is a part of applicationContext-Security.xml
<http auto-config="true" use-expressions="true">
<form-login login-processing-url="/resources/j_spring_security_check" login-page="/login" authentication-failure-url="/login?login_error=t" />
<logout logout-url="/resources/j_spring_security_logout" />
<!-- Configure these elements to secure URIs in your application -->
<intercept-url pattern="/choices/**" access="hasRole('ROLE_ADMIN')" />
<intercept-url pattern="/member/**" access="isAuthenticated()" />
<intercept-url pattern="/resources/**" access="permitAll" />
<intercept-url pattern="/login/**" access="permitAll" />
<intercept-url pattern="/**" access="isAuthenticated()" />
</http>
did you try this?
<http pattern="/home" security='none' />
put it same level with your tag
Try something like this:
<http auto-config="true" use-expressions="true">
<form-login login-processing-url="/resources/j_spring_security_check" login-page="/login" authentication-failure-url="/login?login_error=t" />
<logout logout-url="/resources/j_spring_security_logout" />
<!-- Configure these elements to secure URIs in your application -->
<intercept-url pattern="/choices/**" access="hasRole('ROLE_ADMIN')" />
<intercept-url pattern="/member/**" access="isAuthenticated()" />
<intercept-url pattern="/resources/**" access="permitAll" />
<intercept-url pattern="/login/**" access="permitAll" />
<intercept-url pattern="/index" access="permitAll" /> <!-- new -->
<intercept-url pattern="/" access="permitAll" /> <!-- new -->
<intercept-url pattern="/**" access="isAuthenticated()" />
</http>
The intercep-url evaluates in order and use the first matching permission. So, if you add the "/index" and "/" pattern before "/**" this match will be applied.
So I'm trying to create spring authentication using hibernate. I've checked out probably all of the tutorials about this issue that are available on the internet and yet I seem to be missing something, because when I press the submit button in my form, no authentication is performed and I don't get redirected where I was supposed to be redirected...
This is my security configuration:
<bean id='userDetailsService' class='fi.social.web.services.UserDetailsServiceImpl'></bean>
<security:http auto-config="true">
<security:form-login login-page="/" default-target-url="/welcome"
authentication-failure-url="/loginfailed" />
</security:http>
<bean id='daoAuthenticationProvider' class='org.springframework.security.authentication.dao.DaoAuthenticationProvider'>
<property name='userDetailsService' ref='userDetailsService' />
</bean>
<bean id='authenticationManager' class='org.springframework.security.authentication.ProviderManager'>
<property name='providers'>
<list>
<ref local='daoAuthenticationProvider' />
</list>
</property>
</bean>
<security:authentication-manager>
<security:authentication-provider user-service-ref='userDetailsService'>
<security:password-encoder hash='plaintext' />
</security:authentication-provider>
</security:authentication-manager>
and my JSP page:
<form method="post" name="loginForm" action="<c:url value='j_spring_security_check' />">
<table style="position:absolute; right:15px;">
<tr>
<td><input type="text" name="j_username" placeholder="<fmt:message key="user.usernameOrEmail"/>"/></td>
<td><input type="password" name="j_password" placeholder="<fmt:message key="user.password"/>"/></td>
</tr>
<tr>
<td colspan="2" style="color: white; text-align:right">
<input type="checkbox" name="remember" /><fmt:message key="user.remember" />
<input type="submit" name="submit" style="margin:0px 0px 0px 15px; display:inline;" value="<fmt:message key="user.logIn"/>" />
</td>
</tr>
</table>
</form>
Still, for some reason, when I submit the form I go to
http://127.0.0.1:8080/social/j_spring_security_check;jsessionid=C00D6F0CA27E3B359A9B04B8FADDD87F
even though the spring is supposed to know that my form is there and that it should process the parameters...
So what am I doing wrong?
Have you tried to set up your login form just using <form method="post" name="loginForm" action='#{request.contextPath}/j_spring_security_check'>
Also there is one odd thing on your configuration (but from what you are telling that is not the problem right now):
It's that you are declaring two authentication managers:
<security:authentication-manager>,
<bean id='authenticationManager' class='org.springframework.security.authentication.ProviderManager'>
Try removing
<security:authentication-manager>
<security:authentication-provider user-service-ref='userDetailsService'>
<security:password-encoder hash='plaintext' />
</security:authentication-provider>
</security:authentication-manager>
Authentication and Authorization is working properly. But remember me is not working properly in the application.
I have used both database authentication and ldap authentication using spring security (only one at a time) with lot of spring security customization.
Below is my spring security context file.
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd">
<context:property-placeholder location="classpath:/application.properties"/>
<http use-expressions="true">
<intercept-url pattern="/resources/**" filters="none" />
<intercept-url pattern="/login" access="permitAll"/>
<intercept-url pattern="/**" access="isAuthenticated()" />
<form-login login-page="/login"/>
<logout invalidate-session="true"
logout-success-url="/"
logout-url="/logout"/>
<remember-me key="myApp2" />
<custom-filter before="FORM_LOGIN_FILTER" ref="applicationAuthenticationFilter"/>
</http>
<beans:bean id="applicationAuthenticationFilter" class="com.myApp.security.DmxAuthenticationFilter">
<beans:property name="authenticationManager" ref="authenticationManager"/>
<beans:property name="authenticationFailureHandler" ref="failureHandler"/>
<beans:property name="authenticationSuccessHandler" ref="successHandler"/>
<beans:property name="authenticationMethod" value="${authenticationMethod}"/>
</beans:bean>
<beans:bean id="successHandler"
class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
<beans:property name="defaultTargetUrl" value="/home"/>
<beans:property name="alwaysUseDefaultTargetUrl" value="true"/>
</beans:bean>
<beans:bean id="failureHandler"
class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
<beans:property name="defaultFailureUrl" value="/login?login_error=1"/>
</beans:bean>
<beans:bean id="accessControlService" class="com.myApp.services.AccessControlService"/>
<beans:bean id="userService" class="com.myApp.services.UserService"/>
<beans:bean id="roleService" class="com.myApp.services.RoleService"/>
<beans:bean id="lookupService" class="com.myApp.services.LookupService"/>
<beans:bean id= "userDetailsService" class="com.myApp.security.DmxUsersDetailsServiceImpl">
<beans:property name="accessControlService" ref="accessControlService"/>
</beans:bean>
<beans:bean id="databaseAuthenticationProvider" class="com.myApp.security.DmxAuthenticationProvider">
<beans:property name="userDetailsService" ref="userDetailsService"/>
<!-- <beans:property name="hideUserNotFoundExceptions" value="false"/> -->
</beans:bean>
<!-- ================ LDAP configuration STARTS here ================ -->
<beans:bean id="ldapServer" class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
<beans:constructor-arg value="${ldap.url}"/>
<beans:property name="userDn" value="${ldap.userDn}"/>
<beans:property name="password" value="${ldap.password}"/>
<!--
<beans:property name="baseEnvironmentProperties">
<beans:map>
<beans:entry key="java.naming.referral" value="follow" />
</beans:map>
</beans:property>
-->
</beans:bean>
<beans:bean id="ldapSearchBean" class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
<beans:constructor-arg value="${ldap.userSearchBase}"/>
<beans:constructor-arg value="${ldap.userSearchFilter}"/>
<beans:constructor-arg ref="ldapServer"/>
</beans:bean>
<beans:bean id="ldapAuthenticationProvider" class="com.myApp.security.DmxLdapAuthenticationProvider">
<beans:constructor-arg ref="ldapBindAuthenticator"/>
<beans:constructor-arg ref="ldapAuthoritiesPopulator"/>
<beans:property name="userDetailsContextMapper" ref="ldapUserDetailsContextMapper"/>
</beans:bean>
<beans:bean id="ldapBindAuthenticator" class="org.springframework.security.ldap.authentication.BindAuthenticator">
<beans:constructor-arg ref="ldapServer"/>
<beans:property name="userSearch" ref="ldapSearchBean"/>
</beans:bean>
<beans:bean id="ldapAuthoritiesPopulator" class="com.myApp.security.DmxLdapAuthoritiesPopulator">
<beans:constructor-arg ref="ldapServer" />
<beans:constructor-arg value="" />
<beans:property name="groupSearchFilter" value="${ldap.groupSearchFilter}"/>
<beans:property name="groupRoleAttribute" value="${ldap.groupRoleAttribute}" />
<beans:property name="rolePrefix" value=""/>
<beans:property name="searchSubtree" value="true"/>
<beans:property name="convertToUpperCase" value="false"/>
<beans:property name="ldapTemplate" ref="ldapTemplate"/>
</beans:bean>
<beans:bean id= "dmxUsersMapper" class="com.myApp.security.DmxUsersMapper">
<beans:property name="accessControlService" ref="accessControlService"/>
<beans:property name="userService" ref="userService"/>
<beans:property name="roleService" ref="roleService"/>
<beans:property name="lookupService" ref="lookupService"/>
<beans:property name="organizationUname" value="${organizationUname}"/>
<beans:property name="companyUname" value="${companyUname}"/>
<beans:property name="ldapUsername" value="${ldap.db.userName}"/>
<beans:property name="password" value="${ldap.db.password}"/>
</beans:bean>
<beans:bean class="com.myApp.security.DmxLdapUserDetailsMapper" id="ldapUserDetailsContextMapper">
<beans:property name="dmxUsersMapper" ref="dmxUsersMapper"/>
</beans:bean>
<beans:bean id="ldapTemplate" class="org.springframework.security.ldap.SpringSecurityLdapTemplate">
<beans:constructor-arg ref="ldapServer" />
<beans:property name="ignorePartialResultException" value="true"/>
</beans:bean>
<!-- ================ LDAP configuration ENDS here ================ -->
<authentication-manager alias="authenticationManager">
<authentication-provider ref="databaseAuthenticationProvider" />
<authentication-provider ref="ldapAuthenticationProvider"/>
</authentication-manager>
<beans:bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<beans:property name="basenames">
<beans:list>
<beans:value>com/myApp/resourceBundles/SecurityMessages</beans:value>
</beans:list>
</beans:property>
</beans:bean>
</beans:beans>
Below is my login page.
<form action="j_dmx_security_filter" method="post">
<table border="0" class="section_tbl2">
<tr>
<td><label for="j_organization">Organization</label> </td>
<td> : </td>
<td><input id="j_organization" name="j_organization" size="20" maxlength="50"
type="text" class="txtinput"/></td>
</tr>
<tr>
<td> <label for="j_company">Company</label></td>
<td> : </td>
<td> <input id="j_company" name="j_company" size="20" maxlength="50"
type="text" class="txtinput"/></td>
</tr>
<tr>
<td><label for="j_username">Username</label> </td>
<td> : </td>
<td><input id="j_username" name="j_username" size="20" maxlength="50"
type="text" class="txtinput"/></td>
</tr>
<tr>
<td><label for="j_password">Password</label> </td>
<td> : </td>
<td><input id="j_password" name="j_password" size="20" maxlength="50"
type="password" class="txtinput"/></td>
</tr>
<tr>
<td></td>
<td></td>
<td> <input type="submit" value="Login"/></td>
</tr>
<tr>
<td></td>
<td></td>
<td> <input id="_spring_security_remember_me" name="_spring_security_
remember_me" type="checkbox" value="true"/>
<label for="_spring_security_remember_me">Remember Me?</label></td>
</tr>
</table>
</form>
The remember me token itself is not getting created.
Please help.
in order to help, where are your relevant beans definitions of the RememberMe? such as
<bean id="rememberMeServices" class=
"org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices">
<property name="userDetailsService" ref="jpaUserDetailsService"/>
<property name="key" value="89dqj219dn910lsAc12"/>
</bean>
<bean id="rememberMeAuthenticationProvider" class=
"org.springframework.security.authentication.RememberMeAuthenticationProvider">
<property name="key" value="89dqj219dn910lsAc12"/>
</bean>
(this is too long to be written as a comment, so I wrote it as an "answer"... sorry)
In the Spring security they provide 2 ways to use the rememberMe service.
In the rememberMeService Definition, set a property alwaysRememberMe is true. In this case whenever first time user try to access the secure URL it will take to login page. once user logged in with correct user name and password, after onwards it wil not ask you for login until you logout.
In the login page add a remember me checkbox with name "_spring_security_remember_me" and value="true". In this case when user select the remember me check box then only it will able to access to secure URL without login page until u logout.
Its working for me..
This is how I did and it worked....complete sample of working code is available HERE
<security:http use-expressions='true'>
<security:intercept-url pattern="/protected" access="isAuthenticated()"/>
<security:intercept-url pattern="/**" access="permitAll"/>
<security:form-login login-page="/login" authentication-failure-url="/login?login_error=1" />
<security:logout logout-url="/j_spring_security_logout" />
<security:remember-me services-ref="rememberMeServices" key="testKeyForBlog" />
</security:http>
<bean id="rememberMeServices"
class="org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices">
<property name="tokenRepository" ref="customTokenRepository" />
<property name="userDetailsService" ref="userDetailsService" />
<property name="key" value="testKeyForBlog" />
</bean>
You have to use rememberMeService and pass it to your applicationAuthenticationFilter
rememberMeSevice will be like
<beans:bean id="rememberMeServices" class="org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices">
<beans:property name="userDetailsService" ref="userDetailsService" />
<beans:property name="key" value="myApp2" />
</beans:bean>
Your Authentication will be
<beans:bean id="applicationAuthenticationFilter" class="com.myApp.security.DmxAuthenticationFilter">
<beans:property name="authenticationManager" ref="authenticationManager"/>
<beans:property name="rememberMeServices" ref="rememberMeServices" />
<beans:property name="authenticationFailureHandler" ref="failureHandler"/>
<beans:property name="authenticationSuccessHandler" ref="successHandler"/>
<beans:property name="authenticationMethod" value="${authenticationMethod}"/>
</beans:bean>
This should work
I've added Spring Security to my application. I am able to login fine but after I click logout, I'm then unable to login again.
Here is my applicationContext-security.xml
<http auto-config="true" access-denied-page="/accessDenied.html">
<intercept-url pattern="/login.html*" filters="none"/>
<intercept-url pattern="/static/**" filters="none"/>
<intercept-url pattern="/**" access="ROLE_USER" />
<form-login login-page="/login.html"
authentication-failure-url="/login.html?login_error=1"
default-target-url="/search.html"/>
<logout logout-success-url="/login.html"/>
<concurrent-session-control max-sessions="1" exception-if-maximum-exceeded="true"/>
</http>
<!--
Usernames/Passwords are
rod/koala
-->
<authentication-provider>
<password-encoder hash="md5"/>
<user-service>
<user name="rod" password="a564de63c2d0da68cf47586ee05984d7" authorities="ROLE_USER" />
</user-service>
Here is my login form:
<form method="post" action="j_spring_security_check">
<table>
<tr>
<td><label for="j_username">Username:</label></td>
<td>
<input type="text" name="j_username" id="j_username" size="20" maxlength="50"
<c:if test="${not empty param.login_error}">
value="<%= session.getAttribute(AuthenticationProcessingFilter.SPRING_SECURITY_LAST_USERNAME_KEY) %>"
</c:if>/>
</td>
</tr>
<tr>
<td><label for="j_password">Password:</label></td>
<td>
<input type="password" name="j_password" id="j_password" size="20" maxlength="50"/>
</td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="checkbox" name="_spring_security_remember_me"/> Remember me on this computer.
</td>
</tr>
<tr>
<td> </td>
<td>
<input type="submit" class="button-submit" name="submit" value="Login">
</td>
</tr>
</table>
And my logout link points to:/j_spring_security_logout
UPDATE: (10.30.2009 09:44 EDT)
Some additional info, I enabled DEBUG level logging and can now see this in my console:
09:42:14 DEBUG [http-8080-1] (AbstractProcessingFilter.java:412) - Authentication request failed: org.springframework.security.concurrent.ConcurrentLoginException: Maximum sessions of 1 for this principal exceeded
It would seem that this line from my applicationContext-security.xml has something to do with it:
<concurrent-session-control max-sessions="1" exception-if-maximum-exceeded="true"/>
I'm not sure why even if I've logged out that it thinks I've exceeded the max num of sessions.
Any help appreciated, thanks!
-aj
Actually, I just solved it. ;)
This listener was missing from my web.xml:
<listener>
<listener-class>org.springframework.security.ui.session.HttpSessionEventPublisher</listener-class>
</listener>