I'm using tomcat 6, spring mvc 3.0.0 and spring security 3.0.0, and since the passwords I store in the database are sha1 hashed, I can't use digest authentication (section 9.2.1 of the documentation spells that out). For this reason, I need to make authentication happen through https.
Due to potential processing overhead, I want to keep as much of the traffic in regular http as possible. Is there a way I can make spring use https for unathenticated requests, then use http once authentication is done? I think this is done with a ChannelProcessingFilter of some sort, but I'm stumped as to the particulars.
Here's my application-security.xml file as it currently stands:
<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">
<http use-expressions="true">
<intercept-url pattern="/**" access="isAuthenticated()" />
<http-basic />
</http>
<authentication-manager>
<authentication-provider user-service-ref="myUserDetailsService">
<password-encoder hash="sha"/>
</authentication-provider>
</authentication-manager>
<beans:bean id="myUserDetailsService"
class="path.to.myUserDetailsServiceImpl">
</beans:bean>
</beans:beans>
Thanks for the help.
If at any point you pass a session id over HTTP you are violating OWASP A9. An attacker doesn't need the password if he has the session id. I would not implement this feature in your application, https is very light weight and I think you should look into saving resources in places that doesn't mean that your clients will be hacked.
Not sure exactly how to do it using Spring MVC but I did accomplish this using Grails with Spring Security 3...if you are interested you can see my blog post here.
Because that will not really help you...I did a quick google search and found this post which looks correct and says to configure your web.xml:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/applicationContext-security.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>
and your applicationContext-security.xml as such:
<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.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.1.xsd">
<http>
<intercept-url pattern="/url1.htm"
access="IS_AUTHENTICATED_ANONYMOUSLY" requires-channel="https" />
<intercept-url pattern="/url2.htm"
access="IS_AUTHENTICATED_ANONYMOUSLY" requires-channel="https" />
<intercept-url pattern="/**"
access="IS_AUTHENTICATED_ANONYMOUSLY" requires-channel="http" />
<anonymous />
<http-basic/>
</http>
<!-- This bean is optional; it isn't used by any other bean as it only listens and logs -->
<beans:bean id="loggerListener" class="org.springframework.security.event.authentication.LoggerListener"/>
</beans:beans>
Also take a look at this site for more info and how to configure tomcats SSL connector.
Related
I am using Spring security to secure my rest API. Following are my configurations;
spring-secutiry.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
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">
<security:http auto-config="true">
<!-- Authentication Type and Intercepter Configurations -->
<security:http-basic />
<security:intercept-url pattern="/**" />
<security:anonymous enabled="false" />
<security:session-management invalid-session-url="/">
<security:concurrency-control max-sessions="1" />
</security:session-management>
<security:logout logout-url="/signOff" invalidate-session="true"
delete-cookies="JSESSIONID" logout-success-url="/" />
</security:http>
<bean id="myAuthenticationProvider"
class="com.myauthenticator.spring.secutiry.MyAuthenticationProvider" />
<security:authentication-manager>
<security:authentication-provider ref="myAuthenticationProvider" />
</security:authentication-manager>
</beans>
There is no such implementation for custom logout. I am expecting Spring to intercept call to /signOff and destroys token and redirect me to / because of the configuration in logout-success-url which should challenge for a BASIC auth once more but its loading my home page.
It seems like my spring configurations are not correct i.e. not all calls are intercepted by Spring filter. I have following configurations in my web.xml to priorities my web-fragment which contains my Spring Security Filter;
web.xml
<absolute-ordering>
<name>MyAuthenticator</name>
<others/>
</absolute-ordering>
Note: My filter and custom authentication are implemented as a web-fragment which looks like as follows;
web-fragement.xml
<web-fragment
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
xmlns:webfragment="http://java.sun.com/xml/ns/javaee/web-fragment_3_0.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-fragment_3_0.xsd"
id="T24Authenticator" version="3.0">
<display-name>T24 Authentication Provider</display-name>
<name>MyAuthenticator</name>
<!-- 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>
.....
I think there is something wrong with my configurations! But I can't spot it, can anyone?
I been trying to add some JSF(Face) code into my Spring Webflow project but I am getting the following error:
java.lang.IllegalStateException: FacesContext has not been initialized within the current Web Flow request. Check the configuration for your <webflow:flow-executor>. For JSF you will need FlowFacesContextLifecycleListener configured as one of its flow execution listeners.
Here is my flow.xml file
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:webflow="http://www.springframework.org/schema/webflow-config"
xmlns:faces="http://www.springframework.org/schema/faces"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/webflow-config
http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.3.xsd
http://www.springframework.org/schema/faces
http://www.springframework.org/schema/faces/spring-faces-2.2.xsd">
<!-- Executes flows: the central entry point into the Spring Web Flow system -->
<webflow:flow-executor id="flowExecutor">
<webflow:flow-execution-listeners>
<webflow:listener ref="facesContextListener"/>
</webflow:flow-execution-listeners>
</webflow:flow-executor>
<!-- The registry of executable flow definitions -->
<webflow:flow-registry id="flowRegistry" flow-builder-services="flowBuilderServices" base-path="/WEB-INF">
<webflow:flow-location-pattern value="**/*-flow.xml" />
</webflow:flow-registry>
<!-- Configures the Spring Web Flow JSF integration -->
<faces:flow-builder-services id="flowBuilderServices" />
<!-- A listener maintain one FacesContext instance per Web Flow request. -->
<bean id="facesContextListener"
class="org.springframework.faces.webflow.FlowFacesContextLifecycleListener" />
</beans>
and here is my flow:
<flow xmlns="http://www.springframework.org/schema/webflow"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/webflow
http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">
<var name="customer" class="org.smith.webflowtemplate.domain.Customer"/>
<view-state id="checkbox-input" model="customer" >
<transition on="submit" to="preview" validate="false"/>
<transition on="cancel" to="thanks" validate="false"/>
</view-state>
<view-state id="preview" model="customer">
<transition on="accept" to="endState"/>
</view-state>
<end-state id="endState" view="/index.jsp" />
</flow>
You need to add a Faces Context listener like this:
<flow-executor id="flowExecutor">
<flow-execution-listeners>
<listener ref="facesContextListener" />
</flow-execution-listeners>
</flow-executor>
<beans:bean id="facesContextListener" class="org.springframework.faces.webflow.FlowFacesContextLifecycleListener" />
All,
I have my application setup so that i can use a specific username and password combination:
<?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">
<http use-expressions="true" access-denied-page="/start.jsf">
<intercept-url pattern="/start.jsf" filters="none" />
<intercept-url pattern="/web/**" access="isAuthenticated()" />
<form-login login-page="/start.jsf" default-target-url="/web/user/homepage.jsf" authentication-failure-url="/start.jsf?state=failure"/>
<logout logout-success-url="/start.jsf?state=logout" />
</http>
<!-- <authentication-manager alias="authenticationManager">
<authentication-provider>
<password-encoder hash="md5" />
<jdbc-user-service data-source-ref="dataSource"
users-by-username-query="SELECT U.email_address AS username, U.password as password, 'true' as enabled FROM users U where U.email_address=?"
authorities-by-username-query="SELECT U.email_address AS username, 'USER' as authority FROM users U WHERE U.email_address=?"
role-prefix="ROLE_" />
</authentication-provider>
</authentication-manager> -->
<authentication-manager alias="authenticationManager">
<authentication-provider>
<password-encoder hash="md5"/>
<user-service>
<user name="user1" password="a564de63c2d0da68cf47586ee05984d7" authorities="ROLE_SUPERVISOR, ROLE_USER, ROLE_TELLER" />
</user-service>
</authentication-provider>
</authentication-manager>
</beans:beans>
Problem is that when I ask it to goto the dataSource, it cannot find the datasource. Reason for this is I have another ApplicationContext.xml in a config folder where all my java source files are. How do people normally organize the project so that this file is able to pickup the datasource file? I want to setup the project accordingly...thanks for the input!
Also, the login works, however, once the user logs in, I want to be able to get the userid/password and I'm not able to. How is that possible?
Implying that you have 2 XML files (in classpath) with spring context config: main-ctx.xml and security-ctx.xml and your are instantiating your app context using main-ctx.xml.
Then you can include config from security-ctx.xml into app context using this in main-ctx.xml (depends on your files locations path may be different):
<import resource="classpath:security-ctx.xml"/>
So you can define dataSource in main-ctx.xml and use it in security-ctx.xml in authentication-manager configuration.
I am trying to add UsernameToken based security in web services written using apache cxf version 2.2.12.
Once I deploy my application in weblogic, I am getting two URL's from which I can access my WSDL.
http://localhst:8080/myapp/services/MyService?wsdl
http://localhost:8080/myapp/MyService?wsdl
I am trying to consume webservice using soapUI client and problem is If I use 2nd URL, everything works fine, my ejb is getting injected properly etc but WSS4JInterceptor is not getting called at all.
If I change the URL in soapUI to use 1st one, then Interceptor is getting called but then my services is not getting injected and I am getting NULL as service object.
I have configured WSS4JInterceptor in my spring configuration file. I need to call this Interceptor before each request so that I can verify user token from request header.
Here is my beans.xml
<bean id="wss4jInConfiguration" class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
<property name="properties">
<map>
<entry key="action" value="UsernameToken Timestamp"/>
<entry key="passwordType" value="PasswordText" />
<entry>
<key>
<value>passwordCallbackRef</value>
</key>
<ref bean="passwordCallback"/>
</entry>
</map>
</property>
</bean>
<bean id="passwordCallback" class="my.interceptors.callbacks.handlers.PasswordCallbackHandler"/>
<jaxws:endpoint id="myservice" implementor="my.sample.application.MyServiceImpl"
address="/MyService">
<jaxws:ininterceptors>
<ref bean="wss4jInConfiguration" />
</jaxws:ininterceptors>
</jaxws:endpoint>
Here is my web.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:WEB-INF/beans.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<servlet>
<servlet-name>CXFServlet</servlet-name>
<display-name>CXF Servlet</display-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
</web-app>
I don't have currently access to my WSDL but here is the tag looks like.
<soap:address location="http://localhost:8080/MyServiceSoapPort" />
Any pointer what i am doing wrong.
NOTE: My services are working fine without call back on URL without /services/
My guess is that the Web service is actually deployed twice, once by CXF as configured in your beans.xml file and once by Weblogic as a Java EE 5 Web service. CXF doesn't perform injection (I assume that you are using #EJB), and Weblogic doesn't know anything about your WS-Security configuration.
I am a newbie in Spring based web development.
Our site is Spring based and is currently http based (so quite insecure).
Since, the site is not live yet, we are sending login/password also through a normal JSON request to server and have focussed mostly on JSP, UI design, SQL queries etc.
Now, we want to shift to focus on security and shift to https as a first step.
I have read a no. of web-pages and some spring books but none seems to provide a clear answer on how Spring can be used to provide https security.
Can some one please help me in achieving the above?
Please let me know if my question is not clear. I will try to add more details ASAP.
Our web.xml is as follows:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
"
id="WebApp_ID" version="2.5">
<display-name>Spring3MVC</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
<!--> Mapping for serving static web-content <-->
<!--> The resources folder must be in parallel to WEB-INF <-->
<!--> The mvc:resources gives "not bound" exception unless bound to a namespace as above for xmlns:mvc <-->
<mvc:resources mapping="/resources/**" location="/resources/" />
<mvc:resources mapping="/scripts/**" location="/scripts/" />
</web-app>
There is only one controller right now for which, spring-servlet.xml is as follows:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
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-3.0.xsd">
<context:component-scan
base-package="console.controllerpkg" />
<bean id="viewResolver"
class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
Thanks a lot in advance!
P.S. If you can recommend me a good example based site/book on spring, it would be much appreciated. Most of the sites/books I have seen lay much emphasis on theory but very little examples. That has left me a little confused.
As Dave says, you need to configure your container to serve SSL, and then deploy your spring app into that container. Learn about configuring Tomcat for SSL.
Alternately, and more flexibly you can front your container using Apache, and enable SSL there.
Spring is not 100% responsible for configuring SSL. For that you need to configure the container (jetty, tomcat, etc) to handle SSL.
Thanks for all the help guys.
I will re-iterate what I did just for my own record purposes.
First of all, the link provided by nont about 'Tomcat for SSL' was really helpful.
I read all about SSL and Tomcat there and this is what I did:
On the command prompt, enter:
keytool -genkey -alias tomcat -keyalg RSA
The above command asked me some simple questions needed for a Certificate. I used the password 'changeit' wherever asked (as that is the default password).
On finishing with the above command, it generated a keystore file in C:/Documents and Settings//.keystore
I copied this .keystore file to tomcat/conf/myKeyStore.jks
Then I added the following to conf/server.xml :
<Connector protocol="org.apache.coyote.http11.Http11Protocol"
port="8443" minSpareThreads="5"
maxSpareThreads="75"
enableLookups="true"
disableUploadTimeout="true"
acceptCount="100"
maxThreads="200" debug="5"
scheme="https" secure="true" SSLEnabled="true"
keystoreFile="${catalina.home}/conf/myKeyStore.jks"
keystoreType="JKS" keystorePass="changeit"
truststoreFile="${catalina.home}/conf/cacerts"
truststoreType="JKS" truststorePass="changeit"
SSLVerifyClient="require" SSLEngine="on" SSLVerifyDepth="2"
sslProtocol="TLS" />
And that's it!!
Next time, I ran tomcat my old http link did not work.
Then I tried adding sweet 's' to http with a port number of 8443 and lo! everything was up and running again.
Thanks nont for the wonderful link!!
Configure two different web sites, one for http and one for https, the one for http will have just a redirect to the https site.