How to move username/passwords out of spring-security-context.xml? - spring

I am using Spring Security in one of my project. The web-app requires the user to login. Hence I have added few usernames and passwords in the spring-security-context.xml file as follows:
<authentication-manager>
<authentication-provider>
<user-service>
<user name="user_1" password="password_1" authorities="ROLE_USER" />
<user name="user_2" password="password_2" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
</authentication-manager>
My question is, how to move these username-password pairs to a different file (like some properties file) instead of keeping them in spring-security-context.xml? And how to read that file properties file?

You can store the usernames and passwords in a separate .properties file.
<user-service id="userDetailsService" properties="users.properties"/>
users.properties should have the following format:
jimi=jimispassword,ROLE_USER,ROLE_ADMIN,enabled
bob=bobspassword,ROLE_USER,enabled
If you want to store it in a database, I would recommend you to read this article: http://www.mkyong.com/spring-security/spring-security-form-login-using-database/
Reference: Spring Security In-Memory Authentication

You can use the PropertyPlaceholderConfigurer - put them in properties file and then reference them using EL:
http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/beans.html#beans-factory-placeholderconfigurer

You can find a way to move them to a database or LDAP. Spring Security surely supports both.

I have tried the suggested ways lastly I did the following seemed to work nicely
Added these changes in your web xml
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet-mapping>
<servlet-name>service</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<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>
Add these changes in your spring-security xml
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider>
<security:user-service>
<security:user name="${resource.service.authentication.name}"
authorities="${resource.service.authentication.authorities}"
password="${resource.service.authentication.password}"/>
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
Add these changes into your application context xml or if you have property-loader xml even
better
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="placeholderPrefix" value="${" />
<property name="placeholderSuffix" value="}" />
<property name="locations">
<list>
<value>classpath:resourceservice.properties</value>
</list>
</property>
</bean>
Then Add these changes in your property file resourceservice.properties
memberservice.authentication.name=usename
memberservice.authentication.authorities=AUTHORISED
memberservice.authentication.password=password
Add these changes in you resource that uses Jersey
#PUT
#Path("{accountId}")
#Consumes("application/xml")
#PreAuthorize("hasRole('AUTHORISED')")
public Response methodName

This works for me for Spring security authentication and authorization using Properties file:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.2.xsd">
<mvc:annotation-driven />
<bean id="webPropertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreResourceNotFound" value="true" />
<property name="ignoreUnresolvablePlaceholders" value="true" />
<property name="locations">
<list>
<value>classpath:abc.properties</value>
</list>
</property>
</bean>
<bean
class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
<security:http auto-config="true" use-expressions="true">
<security:intercept-url pattern="/stat/login" access="permitAll"/>
<security:intercept-url pattern="/stat/summary" access="hasRole('ROLE_ADMIN')" />
<security:form-login login-page="/stat/login"
default-target-url="/stat/summary" authentication-failure-url="/stat/loginError" />
</security:http>
<!-- Username and password used from xml -->
<!-- <security:authentication-manager>
<security:authentication-provider>
<security:user-service>
<security:user name="xyz" password="xyz" authorities="ROLE_ADMIN" />
</security:user-service>
</security:authentication-provider>
</security:authentication-manager> -->
<security:authentication-manager>
<security:authentication-provider>
<security:user-service>
<security:user name="${stat.user}" password="${stat.pwd}" authorities="ROLE_ADMIN" />
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
</beans>
The abc.properties file:
stat.user=xyz
stat.pwd=xyz
The web.xml entry for spring-security implementation:
<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>

You can simply add Bean inside your Spring Security Configuration :
#Bean
public UserDetailsService userDetailsService() {
Properties users = PropertiesLoaderUtils.loadAllProperties("users.properties");
return new InMemoryUserDetailsManager(users);
}
and users.properties looks like :
admin={noop}password,ROLE_USER,ROLE_ADMIN,enabled
bob={noop}password,ROLE_USER,enabled
123={noop}123,ROLE_USER,enabled

Related

Spring security XML configuration not protecting URLs

I have gone through a lot of questions similar to this but I couldn't find any solution.
I am using Spring-3.0.5RELEASE and Spring-security-3.1.2RELEASE.
Actually I am adding spring security to already exixsting application.
There are no errors in creating bean or filters but the urls are not protected.
spring-security.xml looks like this:
<?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: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.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<security:http auto-config="true" use-expressions="true">
<!-- <intercept-url pattern="/" access="permitAll" /> -->
<security:intercept-url pattern="/index" access="permitAll" />
<security:intercept-url pattern="/admin"
access="hasRole('Admin')" />
<security:intercept-url pattern="/dashboard" access="hasRole('Admin')
or hasRole('User')" />
<security:intercept-url pattern="/setup" access="hasRole('User')" />
<!-- access denied page -->
<security:access-denied-handler error-page="/logout" />
<security:form-login
login-processing-url="/loginAuth"
login-page="/index"
default-target-url="/dashboard"
username-parameter="username"
password-parameter="password"
authentication-failure-url="/index"/>
<!-- enable csrf protection -->
<!-- <csrf/> -->
<http-basic />
</security:http>
<!-- Select users and user_roles from database -->
<security:authentication-manager>
<security:authentication-provider>
<security:jdbc-user-service data-source-ref="dataSource"
users-by-username-query=
"select customerId, passcode from Users where customerId=?"
authorities-by-username-query=
"select customerId, roleName from Role where customerId=?" />
</security:authentication-provider>
</security:authentication-manager>
</beans:beans>
There is a warning here saying: Referenced bean 'dataSource' not found. I am not sure whether this may cause the problem.
web.xml:
<?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"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<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>
<servlet-name>sample</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/config/sample-servlet.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>sample</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/config/spring-security.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
sample-servlet.xml
<context:property-placeholder location="classpath:resources/database.properties" />
<context:component-scan base-package="com.as.spark" />
<tx:annotation-driven transaction-manager="hibernateTransactionManager"/>
<bean id="jspViewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${database.driver}" />
<property name="url" value="${database.url}" />
<property name="username" value="${database.user}" />
<property name="password" value="${database.password}" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>com.as.spark.model.Users</value>
<value>com.as.spark.model.Role</value>
</list>
</property>
<property name="hibernateProperties">
<!-- properties -->
</property>
</bean>
<bean id="hibernateTransactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
</beans>
I don't want to shift to java configuration because that requires a higher version of spring.
All the pages /home, /dashboard, /admin are open to all users.
How do I check whether the filter is applied? How to protect the URL?

How to implement ResourceUrlEncodingFilter with spring security

I am working on application which is using spring 3.2.3.RELEASE and Spring Security 3.1.4.RELEASE. I want to implement static resource versioning in my application. I did implement this functionality with spring 4.3.11 with this reference http://www.baeldung.com/cachable-static-assets-with-spring-mvc i.e, working fine. Now when I am going to implement this with my old application i.e, not working.I am providing you the code snippet
In my web.xml
<filter>
<filter-name>resourceUrlEncodingFilter</filter-name>
<filter-class>
org.springframework.web.servlet.resource.ResourceUrlEncodingFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>resourceUrlEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<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>
In spring.xml
<security:http auto-config="true" pattern="/**" use-expressions="true">
<!-- Login pages -->
<security:form-login login-page="/login"
default-target-url="/home/"
login-processing-url="/j_spring_security_check"
authentication-failure-url="/login?error" />
<security:logout logout-success-url="/home/"/>
<!-- Security zones -->
<security:intercept-url pattern="/favicon.ico" access="hasRole(ROLE_ANONYMOUS)" />
<security:intercept-url pattern="/login" access="permitAll"/>
<security:intercept-url pattern="/resources/**" access="permitAll"/>
<security:intercept-url pattern="/admin/**" access="hasRole('ROLE_SUPER_USER')" />
<security:intercept-url pattern="/**" access="isAuthenticated()" />
</security:http>
We are also using the caching filter in dispatcher servlet
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/resources/**" />
<bean id="responseCachingFilter" class="org.springframework.web.servlet.mvc.WebContentInterceptor">
<property name="cacheSeconds" value="0" />
<property name="useExpiresHeader" value="true" />
<property name="cacheMappings">
<props>
<prop key="/resources/**">21600</prop>
</props>
</property>
</bean>
</mvc:interceptors>
</mvc:interceptor>
and the versioning code
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/")
.setCacheControl(CacheControl.maxAge(6, TimeUnit.HOURS))
.resourceChain(false)
.addResolver(new VersionResourceResolver().addContentVersionStrategy("/**"))
.addTransformer(new CssLinkResourceTransformer());
}
but my versioning code is not working. Please suggest me where I need to change the code or other approach need to implement.
Thanks In advance

Spring oauth2 ver 2.0.7, 404 error on endpoint /oauth/token

I got problem when try to integrate our web app with Spring oauth2
the end point /oauth/token is mapped for both GET and POST method
o.s.s.o.p.e.FrameworkEndpointHandlerMapping- Mapped "{[/oauth/token],methods=[GET],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public org.springframework.http.ResponseEntity<org.springframework.security.oauth2.common.OAuth2AccessToken> org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.getAccessToken(java.security.Principal,java.util.Map<java.lang.String, java.lang.String>) throws org.springframework.web.HttpRequestMethodNotSupportedException
o.s.s.o.p.e.FrameworkEndpointHandlerMapping- Mapped "{[/oauth/token],methods=[POST],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public org.springframework.http.ResponseEntity<org.springframework.security.oauth2.common.OAuth2AccessToken> org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.postAccessToken(java.security.Principal,java.util.Map<java.lang.String, java.lang.String>) throws org.springframework.web.HttpRequestMethodNotSupportedException
when access: https://192.168.70.19:8072/oauth/token?grant_type=password&client_id=7CA42EA39288EC73212716FC6A51B8A2&username=admin&password=switch
**server return:**Bad client credentials
its ok, however when I add the client_secret
https://192.168.70.19:8072/oauth/token?grant_type=password&client_id=7CA42EA39288EC73212716FC6A51B8A2&client_secret=client_secret&username=admin&password=switch
server return 404 error (as I know this should happen when the API is not mapped only)
Some of my configuration:
<?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"
xmlns:oauth="http://www.springframework.org/schema/security/oauth2"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.2.xsd
http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-1.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetClass"
value="org.springframework.security.core.context.SecurityContextHolder" />
<property name="targetMethod" value="setStrategyName" />
<property name="arguments">
<list>
<value>MODE_INHERITABLETHREADLOCAL</value>
</list>
</property>
</bean>
<bean id="authenticationEntryPoint"
class="com.alu.ov.ngnms.appserver.login.AuthenticationEntryPoint">
<constructor-arg name="loginUrl" value="/login.html" />
</bean>
<bean name="customUserDetailsAuthenticationProvider" class="com.alu.ov.ngnms.appserver.login.CustomUserDetailsAuthenticationProvider">
<property name="aaaServerRepository" ref="AAAServerRepository"></property>
</bean>
<security:authentication-manager alias="authenticationManager"
erase-credentials="false">
<security:authentication-provider ref="customUserDetailsAuthenticationProvider" />
</security:authentication-manager>
<bean id="checkTokenEndPoint"
class="org.springframework.security.oauth2.provider.endpoint.CheckTokenEndpoint">
<constructor-arg name="resourceServerTokenServices" ref="tokenServices"/>
</bean>
<bean id="customAccessDeniedHandler"
class="com.alu.ov.ngnms.appserver.login.CustomAccessDeniedHandler"></bean>
<security:http pattern="/oauth/token" create-session="stateless" entry-point-ref="authenticationEntryPoint" authentication-manager-ref="clientAuthenticationManager">
<security:intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY" />
<security:anonymous enabled="false" />
<security:custom-filter ref="clientCredentialsTokenEndpointFilter" after="BASIC_AUTH_FILTER" />
<security:access-denied-handler ref="customAccessDeniedHandler" />
</security:http>
<security:http use-expressions="true" entry-point-ref="authenticationEntryPoint" create-session="never">
<!-- for all users (login & non-login) -->
<security:intercept-url pattern="/favicon.ico" access="permitAll" />
<security:intercept-url pattern="/bower_components/**" access="permitAll"/>
<security:intercept-url pattern="/locales/**" access="permitAll"/>
<security:intercept-url pattern="/ov_components/**" access="permitAll"/>
<security:intercept-url pattern="/scripts/**" access="permitAll"/>
<security:intercept-url pattern="/styles/**" access="permitAll"/>
<security:intercept-url pattern="/template/**" access="permitAll" />
<security:intercept-url pattern="/webstart/classes/**" access="permitAll" />
<security:intercept-url pattern="/assets/**" access="permitAll" />
<!-- only for non-login users -->
<security:intercept-url pattern="/login.html" access="!isAuthenticated()" />
<security:intercept-url pattern="/upgrade.html" access="!isAuthenticated()" />
<security:intercept-url pattern="/api/login" access="!isAuthenticated()" />
<!-- for all login users -->
<!-- only for admin user & no-license OV -->
<security:intercept-url pattern="/noLicense.html" access="hasAnyRole('ROLE_ADMIN_NO_LICENSE')" />
<security:intercept-url pattern="/**" access="isAuthenticated() and !hasRole('ROLE_ADMIN_NO_LICENSE')" />
<security:access-denied-handler ref="customAccessDeniedHandler"/>
<!-- Add filter to extract access token from request and perform authentication -->
<security:custom-filter ref="customOAuth2AuthenProcessingFilter" before="PRE_AUTH_FILTER" />
<security:expression-handler ref="oauthWebExpressionHandler" />
</security:http>
<bean id="clientCredentialsTokenEndpointFilter" class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
<property name="authenticationManager" ref="clientAuthenticationManager" />
</bean>
<security:global-method-security authentication-manager-ref="authenticationManager" pre-post-annotations="enabled"
secured-annotations="enabled">
</security:global-method-security>
<oauth:authorization-server client-details-service-ref="clientDetails" token-services-ref="tokenServices">
<oauth:authorization-code />
<oauth:implicit />
<oauth:refresh-token />
<oauth:client-credentials />
<oauth:password authentication-manager-ref="authenticationManager"/>
</oauth:authorization-server>
<security:authentication-manager id="clientAuthenticationManager">
<security:authentication-provider user-service-ref="clientDetailsUserService" />
</security:authentication-manager>
<bean id="clientDetailsUserService" class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<constructor-arg ref="clientDetails" />
</bean>
<bean id="tokenServices" class="org.springframework.security.oauth2.provider.token.DefaultTokenServices" >
<property name="tokenStore" ref="mongoDBTokenStore" />
<property name="supportRefreshToken" value="true" />
<property name="clientDetailsService" ref="clientDetails" />
<!-- Access token & Refresh token will be expired in 1 year 1 second after being granted -->
<property name="accessTokenValiditySeconds" value="31536001"></property>
<property name="refreshTokenValiditySeconds" value="31536001"></property>
</bean>
<bean id="ovTokenExtractor" class="com.alu.ov.ngnms.appserver.login.OVTokenExtractor"></bean>
<bean id="oauth2AuthenticationManager" class="org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationManager">
<property name="tokenServices" ref="tokenServices"></property>
</bean>
<bean id="customOAuth2AuthenProcessingFilter" class="org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter">
<property name="authenticationEntryPoint" ref="authenticationEntryPoint"></property>
<property name="authenticationManager" ref="oauth2AuthenticationManager"></property>
<property name="tokenExtractor" ref="ovTokenExtractor"></property>
</bean>
<bean id="clientDetails" class="com.alu.ov.ngnms.appserver.token.CustomClientDetailsService"/>
<security:global-method-security pre-post-annotations="enabled" proxy-target-class="true">
<!--you could also wire in the expression handler up at the layer of the http filters. See https://jira.springsource.org/browse/SEC-1452 -->
<security:expression-handler ref="oauthExpressionHandler" />
</security:global-method-security>
<oauth:expression-handler id="oauthExpressionHandler" />
<mvc:annotation-driven />
<mvc:default-servlet-handler />
<oauth:web-expression-handler id="oauthWebExpressionHandler" />
</beans>
--------EDIT 1--------
added web.xml:
<servlet>
<servlet-name>atmoSpring</servlet-name>
<servlet-class>org.atmosphere.cpr.MeteorServlet</servlet-class>
<init-param>
<!-- When MeteorServlet is used, this is the parameter that will be looked
and all requests will be delegated to this servlet, Of course, since we are
using, Spring MVC, we delegate to DispatcherServlet -->
<param-name>org.atmosphere.servlet</param-name>
<param-value>org.springframework.web.servlet.DispatcherServlet</param-value>
</init-param>
<!-- Bunch of Atmosphere specific properties -->
<init-param>
<param-name>org.atmosphere.cpr.broadcasterClass</param-name>
<param-value>org.atmosphere.cpr.DefaultBroadcaster</param-value>
</init-param>
<!-- Set Atmosphere to use the container native Comet support. -->
<init-param>
<param-name>org.atmosphere.useNative</param-name>
<param-value>true</param-value>
</init-param>
<!-- Force Atmosphere to use stream when writing bytes. -->
<init-param>
<param-name>org.atmosphere.useStream</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>org.atmosphere.cpr.AtmosphereInterceptor</param-name>
<param-value>org.atmosphere.interceptor.SSEAtmosphereInterceptor</param-value>
</init-param>
<init-param>
<param-name>org.atmosphere.interceptor.SSEAtmosphereInterceptor.contentType</param-name>
<param-value>text/event-stream</param-value>
</init-param>
<!-- Use this interceptor to prevent firewall/proxies from canceling the
connection after a specific idle time -->
<init-param>
<param-name>org.atmosphere.cpr.AtmosphereInterceptor</param-name>
<param-value>org.atmosphere.interceptor.HeartbeatInterceptor</param-value>
</init-param>
<init-param>
<param-name>org.atmosphere.interceptor.HeartbeatInterceptor.heartbeatFrequencyInSeconds</param-name>
<param-value>30</param-value>
</init-param>
<init-param>
<param-name>org.atmosphere.useWebSocketAndServlet3</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>org.atmosphere.cpr.AtmosphereInterceptor.disableDefaults</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>org.atmosphere.cpr.broadcasterCacheClass</param-name>
<param-value>org.atmosphere.cache.UUIDBroadcasterCache</param-value>
</init-param>
<init-param>
<param-name>org.atmosphere.cpr.broadcaster.shareableThreadPool</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>org.atmosphere.cpr.sessionSupport</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
</servlet>
<servlet-mapping>
<servlet-name>atmoSpring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/webContext.xml</param-value>
</context-param>
<!-- Spring Security -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<async-supported>true</async-supported>
<init-param>
<param-name>contextAttribute</param-name>
<param-value>org.springframework.web.servlet.FrameworkServlet.CONTEXT.spring</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>ASYNC</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
<filter>
<filter-name>cacheControlFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<async-supported>true</async-supported>
</filter>
<filter-mapping>
<filter-name>cacheControlFilterChain</filter-name>
<url-pattern>/api/*</url-pattern>
</filter-mapping>
<!-- Session Listener for Webstart -->
<listener>
<listener-class>com.alu.ov.ngnms.appserver.controller.SessionListener</listener-class>
</listener>
You can't define the Authorization Server endpoints in a ContextLoaderListener. I don't really know how that MeteorServlet works, but you have to get the configuration into the DispatcherServlet so it can handle the "/oauth/token" requests (the handler is created by the <authorization-server/> declaration).
I also got 404 on /servlet/oauth/token requests. In my case I had the DispatcherServlet mapped to /servlet/*, instead of /* in the web.xml file. I had to update the AuthorizationServerConfigurerAdapter to use a prefix, so that both the authorization filter and the request mapping handler adapter can handle the oauth requests (ie: /servlet/oauth/token for me)
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.prefix("/servlet").authenticationManager(authenticationManager);
}
It was also important to set the DispatcherWebApplicationContextSuffix in the AbstractSecurityWebApplicationInitializer to reference the Dispatcher servlet name from web.xml file.

Securing REST API using Spring-security #PreAuthorize annotation and OAuth2

I'm struggling with some spring-security OAuth2 configuration.
I'm using:
Spring.version: 4.0.5.RELEASE
Spring security version: 3.2.5.RELEASE
Spring security oauth version: 2.0.2.RELEASE
Jersey version: 1.18.1
I want to secure my REST API using the PreAuthorize annotation of Spring security where I define the role that is authorized to access the method:
#Transactional
#POST
#PreAuthorize("hasRole('ROLE_ADMIN')")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public Response create(User user) throws BusinessException {
LOG.info("POST Request: Creation of a new user with username [{}]", user.getUsername());
UserValidator.validateUser(user);
User createdUser = userDao.create(user);
return Response.ok(createdUser).build();
}
When I call the API method with a valid bearer token for a user with role "ROLE_ADMIN", I get following exception:
09-Sep-2014 16:13:40.977 SEVERE [http-nio-8080-exec-6] com.sun.jersey.spi.container.ContainerResponse.mapMappableContainerException The RuntimeException could not be mapped to a response, re-throwing to the HTTP container
org.springframework.security.access.AccessDeniedException: Access is denied
at org.springframework.security.access.vote.AbstractAccessDecisionManager.checkAllowIfAllAbstainDecisions(AbstractAccessDecisionManager.java:70)
at org.springframework.security.access.vote.UnanimousBased.decide(UnanimousBased.java:107)
at ...
When using postman, I see the following error description:
{
"error": "unauthorized",
"error_description": "Full authentication is required to access this resource"
}
This is my security config:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:oauth="http://www.springframework.org/schema/security/oauth2"
xmlns:sec="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.2.xsd
http://www.springframework.org/schema/security/oauth2
http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd">
<context:property-placeholder location="classpath:main.properties"/>
<sec:global-method-security pre-post-annotations="enabled" />
<oauth:expression-handler id="oauthExpressionHandler" />
<!-- Definition of the Authentication Service -->
<sec:http pattern="/oauth/token" create-session="stateless" authentication-manager-ref="clientAuthenticationManager">
<sec:intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY"/>
<sec:anonymous enabled="false"/>
<sec:http-basic entry-point-ref="clientAuthenticationEntryPoint"/>
<!-- include this only if you need to authenticate clients via request parameters -->
<sec:custom-filter ref="clientCredentialsTokenEndpointFilter" after="BASIC_AUTH_FILTER"/>
<sec:access-denied-handler ref="oauthAccessDeniedHandler"/>
</sec:http>
<!-- Protected resources -->
<sec:http auto-config="true"
entry-point-ref="oauthAuthenticationEntryPoint"/>
<bean id="oauthAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="dstest" />
</bean>
<bean id="clientAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="dstest/client"/>
<property name="typeName" value="Basic"/>
</bean>
<bean id="oauthAccessDeniedHandler"
class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler"/>
<bean id="clientCredentialsTokenEndpointFilter"
class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
<property name="authenticationManager" ref="clientAuthenticationManager"/>
</bean>
<bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased">
<constructor-arg>
<list>
<bean class="org.springframework.security.oauth2.provider.vote.ScopeVoter"/>
<bean class="org.springframework.security.access.vote.RoleVoter"/>
<bean class="org.springframework.security.access.vote.AuthenticatedVoter"/>
</list>
</constructor-arg>
</bean>
<!-- Authentication in config file -->
<sec:authentication-manager id="clientAuthenticationManager">
<sec:authentication-provider user-service-ref="clientDetailsUserService"/>
</sec:authentication-manager>
<sec:authentication-manager alias="authenticationManager">
<sec:authentication-provider>
<sec:jdbc-user-service data-source-ref="securityDataSource"/>
</sec:authentication-provider>
</sec:authentication-manager>
<bean id="clientDetailsUserService"
class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<constructor-arg ref="clientDetails"/>
</bean>
<!-- Token Store -->
<bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.store.JdbcTokenStore">
<constructor-arg ref="securityDataSource" />
</bean>
<bean id="oAuth2RequestFactory" class="org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory">
<constructor-arg ref="clientDetails"/>
</bean>
<bean id="tokenServices" class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
<property name="tokenStore" ref="tokenStore"/>
<property name="supportRefreshToken" value="true"/>
<property name="clientDetailsService" ref="clientDetails"/>
<!-- VIV -->
<property name="accessTokenValiditySeconds" value="10"/>
</bean>
<bean id="userApprovalHandler"
class="org.springframework.security.oauth2.provider.approval.TokenStoreUserApprovalHandler">
<property name="tokenStore" ref="tokenStore"/>
<property name="requestFactory" ref="oAuth2RequestFactory"/>
</bean>
<!-- Token management -->
<oauth:authorization-server client-details-service-ref="clientDetails" token-services-ref="tokenServices"
user-approval-handler-ref="userApprovalHandler" token-endpoint-url="/oauth/token">
<oauth:authorization-code/>
<oauth:implicit/>
<oauth:refresh-token/>
<oauth:client-credentials/>
<oauth:password/>
</oauth:authorization-server>
<oauth:resource-server id="resourceServerFilter"
resource-id="dstest"
token-services-ref="tokenServices"/>
<!-- Client Definition -->
<oauth:client-details-service id="clientDetails">
<oauth:client client-id="healthdata-client"
authorized-grant-types="password,authorization_code,refresh_token,implicit,redirect"
authorities="ROLE_CLIENT, ROLE_TRUSTED_CLIENT"
redirect-uri="/web"
scope="read,write,trust"
access-token-validity="300"
refresh-token-validity="6000"/>
</oauth:client-details-service>
</beans>
And this is my web.xml configuration:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
<display-name>Spring MVC Application BASIC AUTH</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:applicationContext.xml
/WEB-INF/rest-dispatcher-servlet.xml
/WEB-INF/security.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</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>
<servlet>
<servlet-name>rest-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>rest-dispatcher</servlet-name>
<url-pattern>/oauth/token</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>Spring servlets</servlet-name>
<servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>be.spring.security.api</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>be.spring;org.codehaus.jackson.jaxrs</param-value>
</init-param>
<!-- optional: JSON support apart from jaxb -->
<init-param>
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Spring servlets</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
I found the solution to my problem. Web security services are configured using the element and I had to alter my protected resource definition from:
<sec:http auto-config="true"
entry-point-ref="oauthAuthenticationEntryPoint"/>
to:
<sec:http auto-config="true">
<sec:custom-filter ref="resourceServerFilter"
before="PRE_AUTH_FILTER"/>
<sec:access-denied-handler
ref="oauthAccessDeniedHandler"/>
</sec:http>
The resourceServerFilter must be referenced in order to be picked up by the security mechanism and the before attribute had to be set to "PRE_AUTH_FILTER".
Also the access-denied-handler is needed if you want proper error handling in a JSON format in the case you can't access the service.

spring mvc 3 (3.2.5) + tiles 3 error 404 not resource found

when i load my app i get only 404 resource not found error.. no logs on tomcat at all..
here you can see my project configuration:
this is my web.xml file:
<?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"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>Spring Web MVC Application</display-name>
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/pages/*</url-pattern>
<!--url-pattern>*.jsp</url-pattern-->
</servlet-mapping>
<urlrewrite default-match-type="wildcard">
<rule>
<from>/</from>
<to>/pages/</to>
</rule>
<rule>
<from>/**</from>
<to>/pages/$1</to>
</rule>
<outbound-rule>
<from>/pages/**</from>
<to>/$1</to>
</outbound-rule>
</urlrewrite>
<filter>
<filter-name>urlRewriteFilter</filter-name>
<filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>urlRewriteFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/mvc-dispatcher-servlet.xml,
/WEB-INF/spring-security.xml,
/WEB-INF/spring-database.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 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>
<welcome-file-list>
<welcome-file>/index.jsp</welcome-file>
</welcome-file-list>
</web-app>
tiles.xml file
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE tiles-definitions PUBLIC
"-//Apache Software Foundation//DTD Tiles Configuration 2.0//EN"
"http://tiles.apache.org/dtds/tiles-config_2_0.dtd">
<tiles-definitions>
<definition name="base.definition"
template="/WEB-INF/pages/layout.jsp">
<put-attribute name="title" value="" />
<put-attribute name="header" value="/WEB-INF/pages/header.jsp" />
<put-attribute name="menu" value="/WEB-INF/pages/menu.jsp" />
<put-attribute name="body" value="" />
<put-attribute name="footer" value="/WEB-INF/pages/footer.jsp" />
</definition>
<definition name="contact" extends="base.definition">
<put-attribute name="title" value="Contact Manager" />
<put-attribute name="body" value="/WEB-INF/pages/prueba2.jsp" />
</definition>
</tiles-definitions>
mvc-dispatcher-servlet.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<context:component-scan base-package="com.mkyong.common.controller" />
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames">
<list>
<value>mymessages</value>
</list>
</property>
</bean>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass">
<value>
org.springframework.web.servlet.view.tiles3.TilesView
</value>
</property>
</bean>
<bean id="tilesConfigurer"
class="org.springframework.web.servlet.view.tiles3.TilesConfigurer">
<property name="definitions">
<list>
<value>/WEB-INF/tiles.xml</value>
</list>
</property>
</bean>
<mvc:annotation-driven />
<mvc:resources mapping="/resources/**" location="/resources/" />
<context:annotation-config />
</beans>
spring-security.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-3.2.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.0.3.xsd">
<!--import resource="../database/spring-database.xml"/-->
<http auto-config="true" access-denied-page="/accessDenied">
<intercept-url pattern="/login*" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/*" access="ROLE_USER" />
<form-login login-page="/login" default-target-url="/prueba2"
authentication-failure-url="/loginfailed.jsp"/>
<logout logout-success-url="/logout" />
</http>
<authentication-manager>
<authentication-provider>
<jdbc-user-service data-source-ref="dataSource"
users-by-username-query="
select username,password, enabled
from users where USERNAME=?"
authorities-by-username-query="
select u.username, ur.authority from users u, user_roles ur
where u.user_id = ur.user_id and u.username =? "
/>
</authentication-provider>
</authentication-manager>
</beans:beans>
this is my controller:
#Controller
#RequestMapping("/prueba2")
public class controller2 extends AbstractController {
Stock stock=new Stock();
List stockList=new ArrayList<Stock>();
ApplicationContext appContext = new ClassPathXmlApplicationContext("spring/config/BeanLocations.xml");
StockBo stockBo = (StockBo)appContext.getBean("stockBo");
/*#RequestMapping(method = RequestMethod.GET)
public Stock returnCustomer(ModelMap model) {
stock=stockBo.findByStockCode("7668");
model.addAttribute("miStock", stock);
return stock;
}*/
protected ModelAndView handleRequestInternal (HttpServletRequest req, HttpServletResponse res) throws Exception{
User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String name = user.getUsername();
Map<String, Object> model = new HashMap<String, Object>();
stockList=stockBo.findAll();
stock=stockBo.findByStockCode("7668");
model.put("listaStock",stockList);
model.put("miStock", stock);
model.put("nombreUsuario", name);
System.out.println("lista objetos--->" + stockList.toString());
return new ModelAndView( "prueba2", "model", model );
}
public StockBo getStockBo() {
return stockBo;
}
public void setStockBo(StockBo stockBo) {
this.stockBo = stockBo;
}
}
I don't know the answer to your question directly, but here's how I'd approach it:
First, if I understand your problem correctly, you're expecting that going to the url http://localhost:8080/SpringExample will redirect you to the login page, but that's not happening (you're seeing a 404). I assume that you've checked that your application is actually deployed to the SpringExample context.
You've several things that could influence how URLs are interpreted and redirected. First, you've got Spring, which maps any request starting with /pages/ to the Spring dispatcher. Next, you've got some URL rewriting, which because it's done in a filter, should happen ahead of the spring dispatcher servlet. You've also got a listener that loads all of the spring context configs. Third, you've got Spring Security which is implemented in a filter. Lastly, you've got the tiles configuration, which could in theory also cause a 404 error if a resource isn't found, though it looks like yours is ok.
This is pretty complex, and if things don't happen in the correct order, you'll have a problem. What I would do is strip out each of these components, and then start adding them back in one by one. First, take everything out except the welcome-file configuration and see if you can get to /index.jsp by going to your url. Then add Spring back in and see if you can still get to it. Then add in URL redirection, then security, then tiles. This will help you to narrow down your problem.
<bean id="viewResolver" class="org.springframework.web.servlet.view.tiles3.TilesViewResolver"/>
<bean id="tilesConfigurer"
class="org.springframework.web.servlet.view.tiles3.TilesConfigurer">
<property name="definitions">
<list>
<value>/WEB-INF/tiles.xml</value>
</list>
</property>
</bean>
Try to write the code =>
No need to write this code tiles integration is enough
/WEB-INF/pages/
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>

Resources