Access a controller before authentication Spring Security - spring

I've been trying to implement a solution for multiple login pages. I currently have a unique LoginController, and all it does is to retrieve the login jsp when somebody request /app_name/login.htm. I want that to stay that way, but also add two more locations: /app_name/customers/login.htm and /app_name/employees/login.htm each one with an individual controller CustomerLoginController and EmployeeLoginController.
So my idea is that employees access through their URL and customer using theirs, but if someone try to access the old login.htm the controller redirects him/her to their respective login using an stored cookie and customer as default.
To me it sounds good, but when I tried to access /app_name/customers/login.htm or /app_name/employees/login.htm it just redirects me to login.htm when I'm not authenticated.
I really don't know why it's not resolving them. Any opinion, suggestion, guide, tutorial, example code or link would be helpful.
The project I'm working on has this configs
Web.xml
<!-- Spring Security -->
<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>
servlet-config.xml
<!-- Controllers Mapping -->
<context:component-scan base-package="com.company.project.controllers">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
security-context.xml
<sec:http auto-config="false" entry-point-ref="authenticationProcessingFilterEntryPoint" access-denied-page="/warning/accessDenied.htm" >
<sec:intercept-url pattern="/employees/login.htm" filters="none" />
<sec:intercept-url pattern="/customers/login.htm" filters="none" />
<sec:intercept-url pattern="/login**" filters="none" />
</sec:http>
<bean id="authenticationProcessingFilterEntryPoint" class="org.springframework.security.ui.webapp.AuthenticationProcessingFilterEntryPoint">
<property name="loginFormUrl" value="/login.htm" />
<property name="forceHttps" value="false" />
</bean>
<bean id="authenticationProcessingFilter" class="org.springframework.security.ui.webapp.AuthenticationProcessingFilter">
<property name="authenticationFailureUrl" value="/login.htm?login_error=1"/>
<property name="defaultTargetUrl" value="/home.htm"/>
<property name="alwaysUseDefaultTargetUrl" value="true"/>
<property name="filterProcessesUrl" value="/j_spring_security_check"/>
</bean>
PD: using Spring 2.5.4 and Spring Security 2.0.4 -_- I Know, but is a fairly sized project and it's been in production for a while

Multiple login pages can be done with 2 separate http declarations:
<http pattern="/customers/**" authentication-manager-ref="customerAuthenticationManager">
<form-login login-page="/customers/login" default-target-url="/customers" login-processing-url="/customers/j_spring_security_check"/>
<logout logout-url="/customers/logout"/>
...
</http>
<http pattern="/employees/**" authentication-manager-ref="employeeAuthenticationManager">
<form-login login-page="/employees/login" default-target-url="/employees" login-processing-url="/employees/j_spring_security_check"/>
<logout logout-url="/employees/logout"/>
...
</http>

Related

Is it the true way to implement spring security & CXF webservice

i create a webservice as below:
web.xml
<display-name>MyService</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/beans.xml,/WEB-INF/spring-security.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>CXFServlet</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
<!-- Spring Security Filter -->
<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>
beans.xml
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>
<context:component-scan base-package="com.*" />
<jaxrs:server id="employeeService" address="/employeeservices">
<jaxrs:providers>
<bean class="org.codehaus.jackson.jaxrs.JacksonJsonProvider" />
</jaxrs:providers>
<jaxrs:serviceBeans>
<ref bean="empService" />
</jaxrs:serviceBeans>
<jaxrs:extensionMappings>
<entry key="xml" value="application/xml" />
<entry key="json" value="application/json" />
</jaxrs:extensionMappings>
</jaxrs:server>
<bean id="empService" class="com.service.impl.EmployeeServiceImpl"/>
<bean id="employeeDao" class="com.dao.EmployeeDao"/>
spring-security.xml
<http auto-config="true" use-expressions="true" create-session="stateless" >
<csrf disabled="true"/>
<http-basic entry-point-ref="restAuthenticationEntryPoint"></http-basic>
<intercept-url pattern="/**" access="hasRole('ROLE_USER')" />
</http>
<beans:bean id="userAuthorService" class="com.auth.UserAuthorService"/>
<beans:bean id="restAuthenticationEntryPoint" class="com.auth.UserBasicAuthenticationEntryPoint">
<beans:property name="realmName" value="Name Of Your Realm"/>
</beans:bean>
<authentication-manager>
<authentication-provider user-service-ref="userAuthorService">
<password-encoder ref="bcryptPasswordEncoder"/>
</authentication-provider>
</authentication-manager>
<beans:bean id="bcryptPasswordEncoder"
class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder">
<beans:constructor-arg name="strength" value="5" />
</beans:bean>
<beans:bean id="loggerListener" class="org.springframework.security.authentication.event.LoggerListener"/>
By this configuration, is it flow of request process? :
request -> Spring security(check authentication) -> cxf -> response.
Are there any issues in this configuration when I deploy it in the real sever? what is the standard configuration when using cxf and spring ?
when i call right uri:http://localhost:8089/MyService/rest/employeeservices/getemployeedetals?employeeId=004. its ok.
But call wrong uri: http://localhost:8089/MyService/rest/employeeservices/getemployeedetallll?employeeId=004. It throw exception:
WARNING: No operation matching request path "/MyService/rest/employeeservices/getemployeedetallll" is found, Relative Path: /getemployeedetal, HTTP Method: GET, ContentType: /, Accept: /,. Please enable FINE/TRACE log level for more details.
Jun 07, 2016 1:55:17 PM org.apache.cxf.jaxrs.impl.WebApplicationExceptionMapper toResponse
WARNING: javax.ws.rs.ClientErrorException
at org.apache.cxf.jaxrs.utils.SpecExceptions.toHttpException(SpecExceptions.java:110)
at org.apache.cxf.jaxrs.utils.ExceptionUtils.toHttpException(ExceptionUtils.java:149)
at org.apache.cxf.jaxrs.utils.JAXRSUtils.findTargetMethod(JAXRSUtils.java:477)
So how can i filter the right uri before access controller class.
Please help me. Thank you.
By this configuration, is it flow of request process? : request ->
Spring security(check authentication) -> cxf -> response.
Yes, because J2EE filters are executed around J2EE servlets (before and after euqeust), so springSecurityFilterChain will be executed before CXFServlet
Are there any issues in this configuration when I deploy it in the
real sever?
This is not necessary with latests versions of CXF
<import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>
Also you are catching in CXFServlet /rest/* but in auth *. Is this an issue? Do you need rest services without authentication? Is difficult to analyze issues if we do not know the context of your system. Detail your doubts and I could try to help
what is the standard configuration when using cxf and spring ?
There is no any recommended configuration, because CXF can be used with spring or standalone, jax-ws or jax-rs, as a server or acting as a client, with authentication executed via spring security or integrated with RequestContextFilter or inInterceptor in jax-rs server or even at global level in CXF bus.
If you are talking about the necessary modules to configure so CXF was executed with spring, you have the needed ones.
For authentication, you could consider use a JWT token instead of a bcrypt passwod.
when i call right
uri:http://localhost:8089/MyService/rest/employeeservices/getemployeedetals?employeeId=004.
its ok. But call wrong uri:
http://localhost:8089/MyService/rest/employeeservices/getemployeedetallll?employeeId=004.
It throw exception:
WARNING: No operation matching request path
This warning is normal. The server is responding with an http error code 404-Not found because there is no resource available at rest/employeeservices/getemployeedetallll
So how can i filter the right uri before access controller class.
CXF is doing for you by returning a 404 if the path is not found. It is the correct behaviour. Do you mean CXF uri filter be executed before spring-security? You can not with this configuration because auth filter is previous.

Spring Controller method executed twice

I have integrated Spring Security with Spring MVC and seeing strange behaviour. Every method in the Controller is executed twice for the same request. I googled for it quite a bit but didn't help much. The closest I could find is this http://forum.springsource.org/archive/index.php/t-83158.html I tried the suggestions without any success.
Here is my web.xml :
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<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>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/appServlet/security-app-context.xml
/WEB-INF/application-context.xml
</param-value>
</context-param>
Here is relevant part of applicationcontext.xml :
<context:component-scan base-package="com.*" />
<context:spring-configured/>
<mvc:annotation-driven />
<context:property-placeholder location="classpath:/conf/myConfig.properties" />
<mvc:resources mapping="/resources/**" location="/resources/" />
The servlet-context.xml only has mapping for the InternalResourceViewResolver
The security-context.xml is as follows :
<http pattern="/resources/**" security="none"/>
<http auto-config="false" create-session="stateless" entry-point-ref="loginUrlAuthenticationEntryPoint" >
<intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/j_spring_security_check" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/accessdenied" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/login" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/logout" access="ROLE_USER"/>
<custom-filter before="SECURITY_CONTEXT_FILTER" ref="cookieSecurityContextFilter" />
<custom-filter position="LOGOUT_FILTER" ref="logoutfilter" />
<custom-filter position="FORM_LOGIN_FILTER" ref="authenticationFilter" />
<custom-filter after="EXCEPTION_TRANSLATION_FILTER" ref="customExceptionFilter" />
</http>
<beans:bean id="logoutfilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
<beans:constructor-arg value="/"/>
<beans:constructor-arg ref="customLogouthandler"/>
</beans:bean>
And then further mapping for the filters.
Am I doing something wrong in the configuration that could lead to the controller being called twice. I have checked the logs and the beans are instantiated only once. Please help.
Thanks in advance.
Just in case someone stumbles on this post and solution posted here thinking it will fix the duplicate requests, please first check if it is your browser/rest client making the additional call.
I wasted many hours trying to configure app and servlet contexts "after seeing the first suggested solution", until I figured it was the rest client on certain browsers (Chrome) creating an additional request for "GET requests on image resources". Curl showed only one method execution.
However, I do agree that it is a good practice to separate controller specific beans and their required Spring beans into servlet-context and keep all common beans in app-context. This is especially important if you have multiple Spring dispatcher servlet- in your web.xml.
Elaborating the previous answer:
You can either define both component-scan and mvc in the same context file to keep it simple.
app-context.xml:
<context:component-scan base-package="..." />
<mvc:annotation-driven />
...
Or separate them as follows:
app-context.xml:
<context:component-scan base-package="....">
<context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
<context:exclude-filter expression="org.springframework.web.bind.annotation.ControllerAdvice" type="annotation"/>
<context:exclude-filter expression="org.springframework.web.bind.annotation.ExceptionHandler" type="annotation"/>
</context:component-scan>
...
servlet-context.xml:
<context:component-scan base-package="...">
<context:include-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
<context:include-filter expression="org.springframework.web.bind.annotation.ControllerAdvice" type="annotation"/>
<context:include-filter expression="org.springframework.web.bind.annotation.ExceptionHandler" type="annotation"/>
</context:component-scan>
<mvc:annotation-driven />
...
I would try moving <mvc:.. elements to servlet-context.xml, maybe having it on applicationContext.xml causes you to have duplicate dispatcher servlet (although beans are only created once)
Scan all components except #Controller on applicationContext.xml by using <context:exclude-filter... Likewise scan only #Controller on servlet-context.xml using <context:include-filter..

Spring security session management and Spring MVC view resolver error

I am working on a Spring MVC web application. Last week I started adding Sping Secuirty to my project. The problem I am facing concerns session management.
Here is http part of my spring-security.xml
<http auto-config="true">
<intercept-url pattern="/css" filters="none"/>
<intercept-url pattern="/js" filters="none"/>
<intercept-url pattern="/logout" filters="none"/>
<intercept-url pattern="/loginfailed" filters="none"/>
<intercept-url pattern="/login" filters="none"/>
<intercept-url pattern="/**" access="ROLE_USER" />
<form-login login-page="/login" default-target-url="/hello"
authentication-failure-url="/loginfailed" />
<session-management invalid-session-url="/login.jsp?error=sessionExpired" session-authentication-error-url="/login.jsp?error=alreadyLogin">
<concurrency-control max-sessions="1" expired-url="/login.jsp?error=sessionExpiredDuplicateLogin" error-if-maximum-exceeded="false"/>
</session-management>
</http>
Login/logout works fine, but when I try to invalidate user session by trying to login from different browser invalid-session-url="/login.jsp?error=sessionExpired" fails. Browser get redirected, because I see that GET request to login.jsp?error=sessionExpired is being sent. However, web page shows error saying that resource is not available. I suspect that it has something to do with
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass">
<value>org.springframework.web.servlet.view.JstlView</value>
</property>
<property name="prefix">
<value>/WEB-INF/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
in my dispatcher-servlet.xml. However, I don't know exactly how to fix this issue. login.jsp is located in WEB-INF/pages/
It seems to me Spring MVC DispatcherServlet couldn't find a mapping for /login.jsp because it's not set as a view that accessible without controller. I'm also assuming you had /login mapped to login.jsp (you did not provide enough info to confirm this), but if this is the case, just use expired-url="/login?error=sessionExpiredDuplicateLogin
You are redirecting to the jsp not the mapped url.
session management tag should be :
<session-management invalid-session-url="/login?error=sessionExpired" session-authentication-error-url="/login?error=alreadyLogin">
<concurrency-control max-sessions="1" expired-url="/login?error=sessionExpiredDuplicateLogin" error-if-maximum-exceeded="false"/>
</session-management>

Spring 2 Security on Glassfish 3 Shows Basic Auth after form Auth

We are trying to upgrade our existing Spring 2.5 based application to Glassfish 3.1.2.2.
This application is working fine on Glassfish 2.1 with Spring 2 security. We are using our custom authentication setup for this.
The application deploys fine on the GF3. When we try to login to application our custom form based authentication page is displayed. Once credentials are provided we get the basic auth popup that is using file realm of GF3 server.
We have already tried these options and it did not work
This SO Thread With no answer
Upgrade Spring version to Last Best Version 2.5.6.SEC03 - This still shows the same issue
Upgrading to Spring 3 is not an option for us since we are stuck with some third party vendor libraries that have compile time dependency on Spring 2.
We already have support from Oracle and they have turned out to be useless(as always their support is disappointing)
Are you aware of any workarounds for this situation?
Below is the security config code we have in web.xml
<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>
<security-constraint>
<web-resource-collection>
<web-resource-name>app</web-resource-name>
<url-pattern>/app/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
</security-constraint>
Below is the security config code we have in spring beans.xml
<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-2.5.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.1.xsd">
<http
access-decision-manager-ref="accessDecisionManager" auto-config="false" realm="SPRING"
session-fixation-protection="none"
servlet-api-provision="true"
entry-point-ref="authEntryPoint"
>
<intercept-url pattern="/Login*" filters="none"/>
<intercept-url pattern="/styles.css" filters="none"/>
<intercept-url pattern="/images/**" filters="none"/>
<intercept-url pattern="/**.js" filters="none"/>
<intercept-url pattern="/**.html" access="users"/>
<intercept-url pattern="/**.htmlx" access="users"/>
</http>
<authentication-manager alias="authenticationManager"/>
<!-- Override of default auth processing filter, to allow custom actions on login
that have access to servlet stuff. This allows access to Tapestry-specifics, for
doing things like creating the custom visit ASO. -->
<beans:bean id="customAuthFilter" class="com.mycomp.core.security.TapestryIntegrationFilter">
<custom-filter position="AUTHENTICATION_PROCESSING_FILTER"/>
<beans:property name="defaultTargetUrl" value="/Home.html"/>
<beans:property name="filterProcessesUrl" value="/j_security_check"/>
<beans:property name="authenticationFailureUrl" value="/Login.html"/>
<beans:property name="authenticationManager" ref="authenticationManager"/>
</beans:bean>
<!-- When using a custom auth filter, you need a custom auth entry point, because you
can't configure this using the "form-login" element under the "http" element. -->
<beans:bean id="authEntryPoint" class="org.springframework.security.ui.webapp.AuthenticationProcessingFilterEntryPoint">
<beans:property name="loginFormUrl" value="/Login.html"/>
</beans:bean>
<!-- This, unfortunately, has to be defined to allow us to remove the "ROLE_" prefix from
rolenames, by defining a roleVoter with an empty prefix. To wire in the voter, you
have to define the access decision manager. -->
<beans:bean id="accessDecisionManager" class="org.springframework.security.vote.AffirmativeBased">
<beans:property name="decisionVoters">
<beans:list>
<beans:bean id="roleVoter" class="org.springframework.security.vote.RoleVoter">
<beans:property name="rolePrefix" value=""/>
</beans:bean>
<beans:bean id="authenticatedVoter" class="org.springframework.security.vote.AuthenticatedVoter"/>
</beans:list>
</beans:property>
</beans:bean>
<!-- PIMA-specific authorization provider. It gets plugged into the framework by using the
custom-authentication-provider element. -->
<beans:bean id="pscAuthenticationProvider" class="com.myapp.core.security.CustomAuthenticationProvider">
<beans:property name="customUserDao" ref="customUserDao"/>
<beans:property name="passwordUtility" ref="passwordUtility"/>
<beans:property name="transactionManager" ref="transactionManager"/>
<custom-authentication-provider/>
</beans:bean>
<beans:bean id="passwordUtility" class="com.myapp.core.security.PasswordUtility">
<!-- Comment/uncomment to toggle password encoding off/on -->
<beans:property name="saltSource">
<beans:bean class="org.springframework.security.providers.dao.salt.SystemWideSaltSource">
<beans:property name="systemWideSalt" value="somegoodsalt"/>
</beans:bean>
</beans:property>
<beans:property name="passwordEncoder">
<beans:bean class="org.springframework.security.providers.encoding.Md5PasswordEncoder"/>
</beans:property>
<!-- -->
</beans:bean>
<beans:bean id="securityService" class="com.scea.core.security.SecurityService">
<beans:property name="passwordUtility" ref="passwordUtility"/>
</beans:bean>

Blazeds and Spring security, can remember-me be used in this combination?

I'm using the latest release of Spring Blzeds integration which has some features making it easier to secure invocations on destination objects. However the basic setup I use which uses the ChannelSet login approach form the flex side looses the authentication information (sessions) on each page refresh. Here's the configuration I'm using:
<http entry-point-ref="preAuthenticatedEntryPoint" >
</http>
<beans:bean id="preAuthenticatedEntryPoint" class="org.springframework.security.ui.preauth.PreAuthenticatedProcessingFilterEntryPoint" />
<beans:bean id="userAccountManager" class="com.comp.service.managers.jpa.UserAccountJpaManager" />
<beans:bean id="userService" class="com.comp.auth.JpaUserDetailsService" />
<beans:bean id="defaultPasswordEncoder" class="com.comp.auth.DefaultPasswordEncoder" />
<authentication-provider user-service-ref="userService">
<password-encoder ref="defaultPasswordEncoder"/>
</authentication-provider>
<flex:message-broker>
<flex:secured />
</flex:message-broker>
<bean id="testService" class="com.comp.service.TestService">
<flex:remoting-destination channels="comp-amf" />
<security:intercept-methods>
<security:protect method="say*" access="ROLE_USER" />
</security:intercept-methods>
</bean>
Is there another way to configure/implement this so I could get persistent sessions (remember me). Is it possible to do the logins from flex over standard HTTP POST (like forms) and still get the same level of granularity for protecting remote object calls?
Try adding this to your config:
<http entry-point-ref="preAuthenticatedEntryPoint" create-session="always">

Resources