I'm new to Java EE / Spring and I've been fighting with security for the past two days. I finally have to the point where I can authenticate with Java EE and authorize with Spring. Unfortunately, I can't access the Java EE authentication from Spring to do the authorization.
The general idea for the application is this:
If you're not logged in, Spring security redirects you to the login page
The login page is the only page that is locked by Java EE. It outputs a form for authentication
After successfully logging in, the user is redirected to the home page, which should have the authentication object associated with it.
Note the emphasis on should since it isn't. For whatever reason, the user is coming back as authenticated but anonymous. If I could simply get the username, I could construct the user details.
Here's the relevant snippets from my 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>
</filter>
<security-constraint>
<web-resource-collection>
<web-resource-name>Home Page Only</web-resource-name>
<description>Rely on Spring for Authorization</description>
<url-pattern>/login</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>*</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>FORM</auth-method>
<form-login-config>
<form-login-page>/login</form-login-page>
<form-error-page>/loginfailed</form-error-page>
</form-login-config>
</login-config>
And my security-content.xml for spring:
<?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"
xmlns:lang="http://www.springframework.org/schema/lang"
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://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<http auto-config='true' use-expressions="true">
<intercept-url pattern="/about" access="permitAll"/>
<intercept-url pattern="/login" access="permitAll"/>
<intercept-url pattern="/loginfailed" access="permitAll"/>
<intercept-url pattern="/css/*" access="permitAll"/>
<intercept-url pattern="/resources/*" access="permitAll"/>
<intercept-url pattern="/images/*" access="permitAll"/>
<intercept-url pattern="/js/*" access="permitAll"/>
<intercept-url pattern="/**" access="hasRole('ROLE_USER')" />
<form-login default-target-url='/index.jsp'
always-use-default-target='true' login-page="/login"
authentication-failure-url="/loginfailed"
/>
</http>
<authentication-manager alias="authenticationManager">
<authentication-provider ref="securityRef"/>
</authentication-manager>
<beans:bean id="securityRef"
class="my.custom.authprovider.AuthenticationProviderImpl"/>
</beans:beans>
Any ideas?
If you want to use Java EE authentication you should configure
PreAuthenticatedProcessingFilter (more precisely J2eePreAuthenticatedProcessingFilter).
Also, you need to configure J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource to populate a user granted authorities:
http://static.springsource.org/spring-security/site/docs/3.1.x/reference/springsecurity-single.html#j2ee-preauth-details
BTW, What advantages do you see to use Java EE Form authentication?
Added after the comment.
If required to use Java EE authentication your approach should be corrected: you should protect the whole application by Java EE authentication.
In this case each request that come to Spring Security will be authenticated by Java EE container and Spring Security can authenticate the request by J2eePreAuthenticatedProcessingFilter.
So the corrected flow
If a user is not logged in, Java EE container redirects the user to the login page
After a successfully authentication, the user is redirected to a page protected by Spring Security. Spring Security can authenticate the request by J2eePreAuthenticatedProcessingFilter.
Related
I found this:
<security:http auto-config="true">
<security:form-login .../>
<security:logout .../>
<security:intercept-url pattern="/reports" access="ROLE_ADMIN" requires-channel="https"/>
<security:intercept-url pattern="/login" access="IS_AUTHENTICATED_ANONYMOUSLY" requires-channel="https"/>
<security:intercept-url pattern="/**" access="ROLE_USER" requires-channel="https"/>
</security:http>
From my understanding we have to place this in web.xml, but we aren't using web.xml, we are using the java configuration. How can I achieve this? Is there anything I can perhaps add in application.properties?
What you are showing is a spring security file. Spring security can be configured either using an XML file (like the one you're showing) or through Java configuration (see here: http://docs.spring.io/spring-security/site/docs/current/reference/html/jc.html).
However your question is: can I enable HTTPS only.
You can also do that through other ways.
In Tomcat for example you can do that by configuring server.xml (http://www.itworld.com/article/2769041/development/how-to-configure-tomcat-to-always-require-https.html and https://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html).
There are similar ways for other JavaEE servers.
You can also use a SecurityConstraint in your web.xml (or Java based Web config) so that it defines CONFIDENTIAL or INTEGRAL like in (XML fragment but you can do it via Java based config):
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
I have a Spring based web application deployed on Tomcat 7. What I do to run it is copy the application.war archive into the webapps directory and start the server, so my application root is available under https://localhost:8443/application/.
Then I wanted to add Spring security (3.2.4) to it. My intention is to secure the entire application, not only parts of it. The Spring security configuration I have:
<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.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.2.xsd">
<http auto-config="true">
<intercept-url pattern="/**" access="ROLE_USER" />
</http>
<authentication-manager>
<authentication-provider>
<user-service>
<user name="admin" password="admin" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
</authentication-manager>
</beans:beans>
And 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>
It's a basic configuration which can be found in the official docs and many tutorials. Everything works fine, when I'm not authenticated Spring redirects me to it's default login page. I can then log in and can access the application until the session expires or I navigate to the logout url.
The problem begins to show up when I access the application root without the trailing slash: https://localhost:8443/application.
Spring fails to find the security context:
2016-07-19 17:48:36,650 DEBUG: security.web.FilterChainProxy - / at position 1 of 12 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2016-07-19 17:48:36,650 DEBUG: web.context.HttpSessionSecurityContextRepository - HttpSession returned null object for SPRING_SECURITY_CONTEXT
2016-07-19 17:48:36,650 DEBUG: web.context.HttpSessionSecurityContextRepository - No SecurityContext was available from the HttpSession: org.apache.catalina.session.StandardSessionFacade#53b1e801. A new one will be created.
I then get redirected to the login page, but after I log in I get redirected to the original URL without the slash, Spring fails again and I see the login form again.
Does anybody know why is this happening? My configuration is minimal, uses out of the box defaults. The use case is also very simple and it feels weird that this is not working as expected. I feel I'm missing something fundamental, either with Spring or Tomcat.
Any help will be appreciated, thanks.
The problem was with the JSESSIONID cookie path -- Tomcat set it automatically to /application/, so any requests accessing the application root without a trailing slash were treated as new users which required authentication. Setting the cookie path to /application solved the problem for me.
just try this
<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>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/</url-pattern>
</filter-mapping>
<http auto-config="true">
<!-- my be this can`t match -->
<intercept-url pattern="/**" access="ROLE_USER" />
<!-- add this for try -->
<intercept-url pattern="/" access="ROLE_USER" />
</http>
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Spring Security Authentication is not working as expected in my configuration
I tried integrating JSF and spring security i spent almost a day but there is no result
Developed an application using JSF,Spring MVC and Primfaces. I am almost done with my requirements, at the end i planned to integrate the spring security but i could n't and i did enough search on net. I feel it may be bug in related framework.
If anyone of you came across the same please post the solution. I post my approach over here
Step 1:
Created Login.jsp(to have customized login page)
Step 2:
Added below code in my 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>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
Step 3:
Created Springsecurity.xml
<sec:global-method-security
secured-annotations="enabled" />
<sec:http auto-config="true" use-expressions="true"
once-per-request="false">
<sec:intercept-url pattern="pages/secured/**"
access="ROLE_USER" />
<sec:form-login login-page="/login.jsp"
default-target-url="/pages/secured/products.xhtml"
authentication-failure-url="/login.html?login_error=1" />
<sec:logout logout-url="/logout" logout-success-url="/login.jsp" />
</sec:http>
<sec:authentication-manager alias="authenticationManager">
<sec:authentication-provider>
<sec:user-service>
<sec:user name="vijay" authorities="ROLE_USER" password="vijay"/>
</sec:user-service>
</sec:authentication-provider>
</sec:authentication-manager>
Executed the application and got the login.jsp as first page since i defind in web.xml. On login authentication its forwarding to the Products.xhtml but i could even access the rest of pages which all are comes under the secured folder with out logging in.
Please suggest a better approach or other alternatives.
For your access attribute have your tried. Your first slash was missing in the pattern.
<sec:intercept-url pattern="/pages/secured/**"
access="hasRole('ROLE_USER')" />
I have two applications, each located on it's own server. Both of them use Spring security with the standart settings.
The problem that I need to access first application through the second one. I need to send password and login to the first application when logging in the second.
Can somebody help with samples or tips please? Thank you.
My spring-security.xml in both applications:
<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 pattern="/favicon.ico" security="none" />
<http auto-config="true">
<intercept-url pattern="/**" access="ROLE_ADMIN"/>
</http>
<authentication-manager>
<authentication-provider>
<user-service>
<user name="hey" password="there" authorities="ROLE_ADMIN" />
</user-service>
</authentication-provider>
</authentication-manager>
you should use CAS for this instead of trying to access or pass user/pass across application.
please refer this link to get understanding how to use CAS in this kind of scenario.
I am using Spring MVC(for REST), Spring Security 3 and Apache Wicket (UI) on Google App Engine. Everything is working fine except I am having trouble in getting the Authentication on the Wicket Page through the SecurityContextHolder after login.
I have google'd this issue, but none seems to be working for me. I suspect this is something wrong with my web xml. Can anyone please help. Thanks.
I am using the tutorials for Spring Security on Google App Engine from http://blog.springsource.org/2010/08/02/spring-security-in-google-app-engine/
Here is my web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<display-name>MTP Portal</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/mtp-web-servlet.xml, /WEB-INF/mtp-web-security-context.xml
</param-value>
</context-param>
<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>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>mtp-web</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>mtp-web</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
<filter>
<filter-name>WicketApp</filter-name>
<filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
<init-param>
<param-name>applicationFactoryClassName</param-name>
<param-value>org.apache.wicket.spring.SpringWebApplicationFactory</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>WicketApp</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Here is my spring security config:
<?xml version="1.0" encoding="UTF-8"?>
<b:beans xmlns="http://www.springframework.org/schema/security"
xmlns:b="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">
<global-method-security pre-post-annotations="enabled"/>
<http pattern="/images/**" security="none"/>
<http pattern="/css/**" security="none"/>
<http pattern="/js/**" security="none"/>
<http pattern="/api/**" security="none"/>
<http pattern="/favicon.ico" security="none"/>
<http pattern="/disabled" security="none"/>
<http use-expressions="true" entry-point-ref="gaeEntryPoint" auto-config="true">
<intercept-url pattern="/" access="permitAll"/>
<intercept-url pattern="/api/**" access="permitAll"/>
<intercept-url pattern="/admin/logout" access="permitAll"/>
<intercept-url pattern="/register" access="hasRole('NEW_USER')"/>
<intercept-url pattern="/admin/**" access="hasRole('ADMIN')"/>
<custom-filter position="PRE_AUTH_FILTER" ref="gaeFilter"/>
</http>
<b:bean id="gaeEntryPoint"
class="com.peerbuccoss.apps.mtp.web.authentication.impl.GoogleAccountsAuthenticationEntryPoint"/>
<b:bean id="gaeFilter" class="com.peerbuccoss.apps.mtp.web.authentication.filter.GaeAuthenticationFilter">
<b:property name="authenticationManager" ref="authenticationManager"/>
<b:property name="failureHandler">
<b:bean class="org.springframework.security.web.authentication.ExceptionMappingAuthenticationFailureHandler">
<b:property name="exceptionMappings">
<b:map>
<b:entry key="org.springframework.security.authentication.DisabledException"
value="/disabled"/>
</b:map>
</b:property>
</b:bean>
</b:property>
</b:bean>
<authentication-manager alias="authenticationManager">
<authentication-provider ref="gaeAuthenticationProvider"/>
</authentication-manager>
<b:bean id="gaeAuthenticationProvider"
class="com.peerbuccoss.apps.mtp.web.authentication.provider.GoogleAccountsAuthenticationProvider"/>
I'm not sure what URL is failing to obtain the SecurityContext (perhaps you can provide an example URL), but the SecurityContext will not be populated for any URL that is mapped to security="none". This is because security="none" instructs Spring Security to ignore this URL entirely. If you need to access the SecurityContext on a URL that is allowed for every user, then you need to use permitAll.
PS: If this does not help you might provide an example URL that you are having trouble with getting the Authentication. You might also provide details on what you mean by "having trouble in getting the Authentication on the Wicket Page" (i.e. is it null, throwing an Exception, etc).