I am new to Spring framework and Spring security. I am developing an application using google app engine. I am trying to authenticate the user but cant able to achieve it. My problems here are
I need to restrict the all the user to type the URL in the browser and to see the pages. If they want to access such pages I need to navigate them to the warning page.
An user can access the application only if he is authenticated with the application. If not authenticated the login page should be navigated.
I need to write a custom login authenticated page where in the page i should authenticate them if given credentials are perfect then we can navigate them to the main page.
In the custom login authentication page we should write the database logic to get the credentials from the db and authenticate. And if the user is not registered with the application then we should navigate them to the registration page with a default message.
Please any one can give me the default application with this requirements.
Thanks and Regards,
Sree
I am using spring 3.x to complete the configuration
in web.xml, add these lines
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
comes to security xml page add these. And i am using DAOAuthenticationProvider. And password encoding i am using BCryptPasswordEncoder.
<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<http use-expressions="true">
<form-login login-page="/login" always-use-default-target="true" default-target-url="/sessionInit" authentication-failure-url="/login"/>
<logout logout-url="/logout" logout-success-url="/logout"/>
</http>
<beans:bean id="daoAuthenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
<beans:property name="userDetailsService" ref="userDetailsService" ></beans:property>
</beans:bean>
<beans:bean id="authenticationManager" class="org.springframework.security.authentication.ProviderManager">
<beans:property name="providers">
<beans:list>
<beans:ref local="daoAuthenticationProvider"/>
</beans:list>
</beans:property>
</beans:bean>
<authentication-manager>
<authentication-provider ref="authProvider"></authentication-provider>
</authentication-manager>
<beans:bean id="authProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
<beans:property name="userDetailsService" ref="userDetailsService" />
<beans:property name="passwordEncoder" ref="encoder" />
</beans:bean>
<beans:bean id="encoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
</beans:beans>
before all these configuration you need add this security.xml file in the web.xml.
Related
I have a java spring mvc web application and I have implemented the login part using spring security. The version of spring security that I use is 3.2.5. My spring-security.xml file is as follows:
<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.2.xsd">
<!-- enable use-expressions -->
<http auto-config="true" use-expressions="true">
<intercept-url pattern="/login" access="isAnonymous()" />
<form-login login-page="/login" default-target-url="/welcome"
authentication-failure-url="/login?error" username-parameter="username"
password-parameter="password" />
<logout logout-success-url="/login?logout" invalidate-session="false" />
<!-- access denied page -->
<access-denied-handler error-page="/403" />
</http>
<beans:bean id="daoAuthenticationProvider"
class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
<beans:property name="userDetailsService" ref="userDetailsService"/>
</beans:bean>
<beans:bean id="authenticationManager"
class="org.springframework.security.authentication.ProviderManager">
<beans:property name="providers">
<beans:list>
<beans:ref local="daoAuthenticationProvider" />
</beans:list>
</beans:property>
</beans:bean>
<!-- Declare an authentication-manager to use a custom userDetailsService -->
<authentication-manager>
<authentication-provider user-service-ref="userDetailsService">
<password-encoder hash="bcrypt" />
</authentication-provider>
</authentication-manager>
</beans:beans>
Now I have a requirement where I will display some content initially and then the user has to login to view the full content. So I provide a sign in link which will bring up the sign in form. But when a user logs in, the default page is shown. I want the user to be redirected to the URL where the user is already in. I have also tried to POST the form to one of my custom controller methods and then redirect to spring security check from there. I intend to store the current URL to session from the method and redirect the user to that method from the default target method of spring security. But redirecting to spring security check is always giving me invalid username or password error since it is not able to authenticate the user. My custom method would be as follows:
#RequestMapping(value = "/edu-login", method = RequestMethod.POST)
public String eduLogin(#ModelAttribute ("username") String username, #ModelAttribute ("password") String password, Model model, HttpServletRequest request, HttpServletResponse response, RedirectAttributes ra)
{
//My custom logic to stroe url to session
ra.addAttribute("username", username);
ra.addAttribute("password", password);
return "redirect:/j_spring_security_check";
}
Is there any solution for my problem. All I want is the user to return to the url on the browser after login.
There is a solution for your use case, but that's not the correct flow you should apply. More over, you cannot use RedirectAttributes this way, as it only applies in MVC layer and the form-loginfilter is in filter layer.
The sequence you are trying to achieve is this:
public_url > [login:if required] > private_url
For such a flow, there is a component you could take advantage of, which is org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler. As it states in the javadoc:
An authentication success strategy which can make use of the DefaultSavedRequest which may have been stored in the session by the ExceptionTranslationFilter. When such a request is intercepted and requires authentication, the request data is stored to record the original destination before the authentication process commenced, and to allow the request to be reconstructed when a redirect to the same URL occurs. This class is responsible for performing the redirect to the original URL if appropriate.
So, let's say your existing unprotected url is /public/edu and the second url (the protected one) is /private/edu.
In /public/edu you should provide a link to /private/edu. While accesing /private/edu the SpringSecurityFilterChain would check if the user is authenticated and have the required authorizations.
If the user is already authenticated the url will be reached directly.
If not, it will redirected to login while it keeps the requested url /private/edu temporaly in session. Once the user performs a correct login, the SavedRequestAwareAuthenticationSuccessHandler will redirect the user to /private/edu instead of the default success url page.
This could be a sample config:
<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.2.xsd">
<!-- enable use-expressions -->
<http auto-config="true" use-expressions="true">
<intercept-url pattern="/login" access="isAnonymous()" />
<intercept-url pattern="/private/edu" access="isAnonymous()" />
<form-login
login-page="/login"
authentication-success-handler-ref="savedRequestSuccesHandler"
authentication-failure-url="/login?error"
username-parameter="username"
password-parameter="password" />
<logout logout-success-url="/login?logout" invalidate-session="false" />
<!-- access denied page -->
<access-denied-handler error-page="/403" />
</http>
<beans:bean id="savedRequestSuccesHandler"
class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
<beans:property name="defaultTargetUrl" value="/welcome" />
</beans:bean>
<beans:bean id="daoAuthenticationProvider"
class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
<beans:property name="userDetailsService" ref="userDetailsService"/>
</beans:bean>
<beans:bean id="authenticationManager"
class="org.springframework.security.authentication.ProviderManager">
<beans:property name="providers">
<beans:list>
<beans:ref local="daoAuthenticationProvider" />
</beans:list>
</beans:property>
</beans:bean>
<!-- Declare an authentication-manager to use a custom userDetailsService -->
<authentication-manager>
<authentication-provider user-service-ref="userDetailsService">
<password-encoder hash="bcrypt" />
</authentication-provider>
</authentication-manager>
</beans:beans>
Note I've removed the default-target-url="/welcome" of the <http> element and introduced the property authentication-success-handler-ref="savedRequestSuccesHandler" which referers to a new bean I've just created:
<beans:bean id="savedRequestSuccesHandler"
class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
<beans:property name="defaultTargetUrl" value="/welcome" />
</beans:bean>
We are trying to migrate the Spring Security 2.0.5 to 3.0.8. Changes are working in Tomcat and Weblogic Server with SSL enabled but no F5 Load balancer. But when deployed application on Weblogic 12.c with two Nodes in it and having F5 Load balancer, it started failing. Before this deployment application was working good, but after this deployment it behaving weirdly. On IE , login button throws error as "Network Error" and sometimes SSL error and on chrome , you can login but page is getting stuck . Can any body please help.
Here are the changes
applicationContext-security.xml (2.0.5)
1. <global-method-security />
2. <intercept-url pattern="/bs/systemCheck.action" filters="none"
access="IS_AUTHENTICATED_ANONYMOUSLY"/>
3. <beans:bean id="authenticationManager"
class="org.springframework.security.providers.ProviderManager">
<beans:property name="providers">
<beans:list>
<beans:ref local="daoAuthenticationProvider" />
</beans:list>
</beans:property>
</beans:bean>
applicationContext-security.xml (3.0.8)
1. <global-method-security pre-post-annotations="enabled" secured-
annotations="enabled"/>
2. <intercept-url pattern="/bs/systemCheck.action" filters="none"/>
3. <beans:bean id="authenticationManager"
class="org.springframework.security.authentication.ProviderManager">
<beans:property name="providers">
<beans:list>
<beans:ref local="daoAuthenticationProvider"/>
</beans:list>
</beans:property>
</beans:bean>
4. <custom-filter ref="logoutFilter" position="LOGOUT_FILTER"/>
<custom-filter ref="authenticationProcessingFilter"
position="FORM_LOGIN_FILTER"/>
<custom-filter ref="switchUserProcessingFilter" position="SWITCH_USER_FILTER"/>
5. <!-- Protects against session fixation -
defaulting to new session & migrate session-->
<session-management session-authentication-strategy-
ref="sessionAuthenticationStrategy"/>
<beans:property name="basicStructureManager"
ref="basicStructureManager"/>
<beans:property name="accountManager" ref="accountManager" />
<!-- Note - this is very important otherwise we get response
committed issue-->
<beans:property name="continueChainBeforeSuccessfulAuthentication"
value="false" />
6. <beans:bean id="successHandler"
class="org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler">
<beans:property name="defaultTargetUrl" value="/bs/home.action"/>
<beans:property name="alwaysUseDefaultTargetUrl" value="true"/>
</beans:bean>
7. <beans:bean id="failureHandler"
class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
<beans:property name="defaultFailureUrl" value="/bs/login.action?loginError=1"/>
</beans:bean>
And in web.xml added
<!-- Required by Spring security to handle session strategy -->
<listener>
<listener-class>
org.springframework.security.web.session.HttpSessionEventPublisher
</listener-class>
</listener>
This Problem is totally different but showing different error message. Some code change happened, for that used "clone" on domain object(Which is a very big Object). So all the connections are occupied and there are no resource for new request.
I've run into a such situation: my application has several roles(administrator, moderator, user). Moderator and User can edit some forms. All permisions are ok. But when I'm loggen in as a user(role User) and change an id in the url, I can simply get and edit form of another user(role User).
How to deny access and prevent such actions?
ps. version of spring and spring security is 3.1.2
update - added spring security context
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<http use-expressions="true" auto-config="false"
entry-point-ref="authenticationEntryPoint" access-denied-page="/403.jsp">
<form-login login-page="/login.html"
authentication-failure-url="/login.html?error=true"
login-processing-url="/j_spring_security_check"
authentication-success-handler-ref="successHandler" />
<logout logout-url="/logout" logout-success-url="/login.html" />
<intercept-url pattern="/admin/**" access="hasRole('adminViewPermission')" />
<intercept-url pattern="/moderator/**" access="hasRole('moderatorViewPermission')" />
<intercept-url pattern="**/form-management"
access="hasRole('formManagementPermission')" />
</http>
<authentication-manager alias="authenticationManager">
<authentication-provider user-service-ref="userDetailsService" />
</authentication-manager>
<beans:bean id="authenticationEntryPoint"
class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<beans:property name="loginFormUrl" value="/login.html" />
<beans:property name="forceHttps" value="false" />
</beans:bean>
<beans:bean id="successHandler"
class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
<beans:property name="defaultTargetUrl" value="/authenticate" />
<beans:property name="alwaysUseDefaultTargetUrl" value="true"/>
</beans:bean>
<beans:bean id="userDetailsService"
class="com.jack.MyYserDetailsService">
</beans:bean>
</beans:beans>
It looks like you want take into account actual domain object for your security rule. Normal SpringSecurity setup with users and roles can add security rules like this: who (athenticated user with some role) may access to some URL / method invocation. If you want to be able use enhanced rules like this: who (athenticated user with some role) may access to some URL / method invocation and what domain objects he can use then you need to use ACL feature.
EDIT. But if you need just one security rule like this then set up ACL may be an overkill. You can try enhance your actual SpringSecurity setup by custom web security expression:
<intercept-url pattern="/moderator/**" access="hasRole('moderatorViewPermission') and userIsAuthor()" />
Where your userIsAuthor() method will:
extract id of the object from the URL (I suppose something like /moderator/item/56)
check if current user is an author of an item id = 56.
I have an application that uses SwitchUserFilter. The switching and exiting works fine in normal cases, but if we give the exit url when the user has not actually switched, the user is logged out (expectedly), but when he tries to login again, the application tries to redirect him to the last page that he tried to access (i.e the switch user url).. where again, the user is found to have not switched, and so an error is thrown, the user is logged off, and so the cycle continues.
The following is my spring configuration file :
<?xml version="1.0" encoding="UTF-8"?>
<!-- - Sample namespace-based configuration - -->
<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd">
<global-method-security pre-post-annotations="enabled">
<!-- AspectJ pointcut expression that locates our "post" method and applies
security that way <protect-pointcut expression="execution(* bigbank.*Service.post*(..))"
access="ROLE_TELLER"/> -->
</global-method-security>
<http use-expressions="true">
<intercept-url pattern="/**" access="isAuthenticated()" />
<custom-filter after="FILTER_SECURITY_INTERCEPTOR" ref="switchUserProcessingFilter" />
<form-login />
<logout invalidate-session="true" logout-url="/do/logout" />
</http>
<!-- Usernames/Passwords are rod/koala dianne/emu scott/wombat peter/opal -->
<authentication-manager>
<authentication-provider>
<user-service id="userService">
<user name="rod" password="koala" authorities="supervisor, teller, user" />
<user name="dianne" password="emu" authorities="teller, user" />
<user name="scott" password="wombat" authorities="user" />
<user name="peter" password="opal" authorities="user" />
</user-service>
</authentication-provider>
</authentication-manager>
<beans:bean id="switchUserProcessingFilter"
class="org.springframework.security.web.authentication.switchuser.SwitchUserFilter">
<beans:property name="userDetailsService" ref="userService">
</beans:property>
<beans:property name="switchUserUrl" value="/switchUser" />
<beans:property name="exitUserUrl" value="/exitUser" />
<beans:property name="targetUrl" value="/index.jsp" />
</beans:bean>
</beans:beans>
Any suggestions as to how can I handle it ?
A practical case could be when I have switched the user, and the session times out. Not knowing that the session has timed out, the user tries to click on the 'exit user' url, which then redirects him to the login page, and the above cycle continues.
As mentioned in this thread, I implemented a custom login success handler, mimicking SavedRequestAwareAuthenticationSuccessHandler, which is the default login success handler. It
retrieves the url that we tried to access before being redirected to the login page from the request cache (where it was stored by ExceptionTranslationFilter, on seeing that we weren't authenticated) and redirects to that url. I simply configured it to go to the root url when it encountered something like 'exitUser'
I'm setting up REST services that requires simple Basic Auth on top of an existing application. The thing is that the security context already has a http tag from the actual application so as simple as it is to set up Basic Auth using the tag, I can't use it because there is already one there with totally different config (see why: https://jira.springsource.org/browse/SEC-1171 I'm using 3.0.4, waiting until 3.1 is released is a possibility but undesired).
How could I exclude my REST services from the pre-existing config and give them Basic Auth?
This is the aplicationContext-security.xml I've been playing around on top of the tutorial sample application. As it is, it has never prompted me to enter my credentials and I don't know what to add.
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd">
<global-method-security pre-post-annotations="enabled">
</global-method-security>
<beans:bean id="filterChainProxy" class="org.springframework.security.web.FilterChainProxy">
<filter-chain-map path-type="ant">
<filter-chain pattern="/**" filters="basicAuthenticationFilter" />
</filter-chain-map>
</beans:bean>
<beans:bean id="basicAuthenticationFilter"
class="org.springframework.security.web.authentication.www.BasicAuthenticationFilter">
<beans:property name="authenticationManager" ref="authManager" />
<beans:property name="authenticationEntryPoint" ref="authenticationEntryPoint" />
</beans:bean>
<beans:bean id="authenticationEntryPoint" class="org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint">
<beans:property name="realmName" value="ems" />
</beans:bean>
<beans:bean id="filterSecurityInterceptor" class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
<beans:property name="authenticationManager" ref="authManager"/>
<beans:property name="accessDecisionManager" ref="accessDecisionManager"/>
<beans:property name="securityMetadataSource">
<filter-security-metadata-source>
<intercept-url pattern="/secure/extreme/**" access="ROLE_SUPERVISOR"/>
<intercept-url pattern="/secure/**" access="ROLE_USER" />
<intercept-url pattern="/**" access="" />
</filter-security-metadata-source>
</beans:property>
</beans:bean>
<beans:bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
<beans:property name="decisionVoters">
<beans:list>
<beans:bean class="org.springframework.security.access.vote.RoleVoter" />
</beans:list>
</beans:property>
</beans:bean>
<beans:bean id="exceptionTranslationFilter"
class="org.springframework.security.web.access.ExceptionTranslationFilter">
<beans:property name="authenticationEntryPoint" ref="authenticationEntryPoint"/>
<beans:property name="accessDeniedHandler" ref="accessDeniedHandler"/>
</beans:bean>
<beans:bean id="accessDeniedHandler" class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
</beans:bean>
<beans:bean id="securityContextPersistenceFilter" class="org.springframework.security.web.context.SecurityContextPersistenceFilter"/>
<!--
Usernames/Passwords are
rod/koala
dianne/emu
scott/wombat
peter/opal
-->
<authentication-manager alias="authManager">
<authentication-provider>
<password-encoder hash="md5"/>
<user-service>
<user name="rod" password="a564de63c2d0da68cf47586ee05984d7" authorities="ROLE_SUPERVISOR, ROLE_USER, ROLE_TELLER" />
<user name="dianne" password="65d15fe9156f9c4bbffd98085992a44e" authorities="ROLE_USER,ROLE_TELLER" />
<user name="scott" password="2b58af6dddbd072ed27ffc86725d7d3a" authorities="ROLE_USER" />
<user name="peter" password="22b5c9accc6e1ba628cedc63a72d57f8" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
</authentication-manager>
I managed to do it by creating a second dispatcherServlet and filterChainProxy on the web.xml, and then creating a second security-context.xml specified on the of the servlets, where I could use the tag again as it was a new context. The gotcha was to set the servletContext attribute of the filters on the web.xml so that they belonged to the appropriate spring context. This is an example of one of the filters and it corresponding servlet.
<filter>
<filter-name>filterChainProxy</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<param-name>contextAttribute</param-name>
<param-value>org.springframework.web.servlet.FrameworkServlet.CONTEXT.servletName</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>filterChainProxy</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>servletName</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
pathTo/servletName-servlet.xml,
pathTo/spring-security.xml
</param-value>
</init-param>
</servlet>