I am using Spring mvc within url rewrite tucky to have extension less Urls. All is working fine but I recently have a problem to handle /j_spring_security_check post.
here are my config files
urlrewrite.xml
<rule>
<from>/$</from>
<to type="forward">home</to>
</rule>
<rule>
<from>/signup$</from>
<to type="forward">/signup</to>
</rule>
<rule>
<from>/j_spring_security_check(\?.*)</from>
<to last="true">/j_spring_security_check$1</to>
</rule>
<rule>
<from>/logout(\?.*)</from>
<to last="true">/logout$1</to>
</rule>
<rule>
<from>^([^?]*)/([^?/\.]+)(\?.*)?$</from>
<to last="true">$1/$2.htm$3</to>
</rule>
<outbound-rule>
<from>^(.*)\.htm(\?.*)?$</from>
<to last="false">$1$2</to>
</outbound-rule>
spring security `
<!-- This is where we configure Spring-Security -->
<security:http auto-config="true" use-expressions="true" access-denied-page="/denied.htm">
<security:intercept-url pattern="/**" access="permitAll" />
<security:intercept-url pattern="/admin/**" access="hasRole('ROLE_ADMIN')" />
<security:intercept-url pattern="/user" access="hasRole('ROLE_USER')" />
<security:form-login login-page="/signup" authentication-failure-url="/signup?error=authenticate" default-target-url="/" />
<security:logout invalidate-session="true" logout-success-url="/" logout-url="/logout" />
<security:remember-me key="springRocks" user-service-ref="userDetailsService"/>
</security:http>
<!-- Declare an authentication-manager to use a custom userDetailsService -->
<security:authentication-manager>
<security:authentication-provider user-service-ref="userDetailsService">
<security:password-encoder ref="passwordEncoder" />
</security:authentication-provider>
</security:authentication-manager>
<!-- Use a Md5 encoder since the user's passwords are stored as Md5 in the
database -->
<bean
class="org.springframework.security.authentication.encoding.Md5PasswordEncoder" id="passwordEncoder" />
<bean id="userDaoService" class="com.dolo.dao.jdbc.JdbcUserDao">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="userDetailsService" class="com.dolo.services.impl.UserServiceImpl">
</bean>
<bean id="userDetails" class="com.dolo.model.User">
</bean>
`
web.xml
<servlet>
<servlet-name>dolo</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
...
<servlet-mapping>
<servlet-name>dolo</servlet-name>
<url-pattern>*.htm</url-pattern>
...
<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>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
....
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
....
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>ERROR</dispatcher>
Both can work together without any problem
<filter-mapping> declaration for springSecurityFilterChain should be done before UrlRewriteFilter one. Once that is done, you don't need any rewrite rule for j_spring_security_check.
Related
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
I struggle with configuration of spring security Oauth to use it on a Struts2 Application to secure rest webservices.
I already use spring security for a long time.
The issue, if I have well understantood, is that Spring security Oauth need spring mvc dispatcher set on root. And this is conflicting with Struts2.
Here are my attempts
2) Struts2 on root and Spring MVC on /oauth/*
<!-- Struts 2 -->
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/struts/*</url-pattern>
</filter-mapping>
<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>/*</url-pattern>
</servlet-mapping>
This is OK for Oauth but Struts2 doesn't work anymore.
1) Struts2 and Spring MVC on root
<!-- Struts 2 -->
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/struts/*</url-pattern>
</filter-mapping>
<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>/oauth/*</url-pattern>
</servlet-mapping>
Struts2, oauth is recognizing rights but the response is made on /token instead of /oauth/token and so I get a 404 error.
The extract of spring-security.xml is here:
<http pattern="/oauth/token" create-session="stateless"
authentication-manager-ref="clientAuthenticationManager"
xmlns="http://www.springframework.org/schema/security">
<intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY" />
<anonymous enabled="false" />
<http-basic entry-point-ref="clientAuthenticationEntryPoint" />
<!-- include this only if you need to authenticate clients via request
parameters -->
<custom-filter ref="clientCredentialsTokenEndpointFilter" after="BASIC_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<!-- This is where we tells spring security what URL should be protected
and what roles have access to them -->
<http pattern="/api/**.api" create-session="never"
entry-point-ref="oauthAuthenticationEntryPoint"
access-decision-manager-ref="accessDecisionManager"
xmlns="http://www.springframework.org/schema/security">
<anonymous enabled="false" />
<intercept-url pattern="/api/**.api" access="ROLE_API" />
<custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
The solution is to use 2 different Spring Dispatchers :
<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>/oauth/*</url-pattern>
</servlet-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>/restapi/*</url-pattern>
</servlet-mapping>
One for the Rest WS and the other for securization.
Afterward you will bet the token not on /oauth/token but on /oauth/oauth/token
To solve this problem you have to duplication Spring Security Parameterization :
<http pattern="/oauth/token" create-session="stateless"
authentication-manager-ref="clientAuthenticationManager"
xmlns="http://www.springframework.org/schema/security">
<intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY" />
<anonymous enabled="false" />
<http-basic entry-point-ref="clientAuthenticationEntryPoint" />
<!-- include this only if you need to authenticate clients via request
parameters -->
<custom-filter ref="clientCredentialsTokenEndpointFilter" after="BASIC_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<http pattern="/oauth/oauth/token" create-session="stateless"
authentication-manager-ref="clientAuthenticationManager"
xmlns="http://www.springframework.org/schema/security">
<intercept-url pattern="/oauth/oauth/token" access="IS_AUTHENTICATED_FULLY" />
<anonymous enabled="false" />
<http-basic entry-point-ref="clientAuthenticationEntryPoint" />
<!-- include this only if you need to authenticate clients via request
parameters -->
<custom-filter ref="clientCredentialsTokenEndpointFilter" after="BASIC_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
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.
I've tried and tried, but seems like i'm unable to make the spring security annotation work. I've refer to alot of sites.. and i cant seems to see what's wrong with my code. any help will be much appreciated
Here is spring security xml
<security:global-method-security pre-post-annotations="enabled"/>
<security:http auto-config="true" use-expressions="true">
<security:intercept-url pattern="/login" access="permitAll" />
<security:intercept-url pattern="/logout" access="permitAll" />
<security:intercept-url pattern="/accessdenied" access="permitAll" />
<security:intercept-url pattern="/**/*.css" access="permitAll" />
<security:intercept-url pattern="/**/*.js" access="permitAll" />
<security:intercept-url pattern="/**" access="hasRole('LANDING')" />
<security:form-login login-page="/login" default-target-url="/landing" authentication-failure-url="/login" authentication-success-handler-ref="loginSuccesHandler" />
<security:logout logout-success-url="/logout" />
</security:http>
here is my web.xml
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<filter>
<filter-name>XSSFilter</filter-name>
<filter-class>simptex.my.core.security.filter.XSSFilter</filter-class>
</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>
<filter-mapping>
<filter-name>XSSFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/dispatcher-servlet.xml
/WEB-INF/application-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>
here is a sample of java code
#PreAuthorize("hasAuthority('ROLE_TELLER')")
#RequestMapping(value = "/urlxxxx" , method = RequestMethod.GET)
public String controlerMethod(HttpServletRequest req, HttpSession session) {
return "urlxxxx";
}
Firstly I think you're using the wrong expression. According to the Spring documentation here, I don't see a hasAuthority() expression. There is however a hasRole() expression. So in your case I believe you need to change the annotation to #PreAuthorize("hasRole('ROLE_TELLER')").
Secondly, the Spring Documentation states:
To use hasPermission() expressions, you have to explicitly configure a PermissionEvaluator in your application context
So in your security XML configuration use the following bean declaration:
<bean id="expressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler" />
And then update your security:global-method-security definition to look something like:
<security:global-method-security pre-post-annotations="enabled">
<security:expression-handler ref="expressionHandler"/>
</security:global-method-security>
That should be enough to get the default Spring Security annotations running out of the box.
i'm working with spring security 3.1.3 in a spring 3.2.0 project. I've configured two entry points for my security using spring security. The idea is to have a url like /enterprise_login where enterprise users should log in and other url like /login where normal users do their log in action. In my security configuration i've the next code
<security:global-method-security jsr250-annotations="enabled" pre-post-annotations="enabled" secured-annotations="enabled" />
<security:http pattern="/enterprise/**" auto-config="false" use-expressions="true" authentication-manager-ref="autenticationManagerUserEnterprise">
<security:intercept-url pattern="/enterprise/**" access="hasRole('ROLE_ENTERPRISE')" />
<security:intercept-url pattern="/enterprise_login" access="isAnonymous()" />
<security:form-login login-page="/enterprise_login" default-target-url="/" authentication-failure-url="/empresas_login_error" login-processing-url="/enterprise_login_process" />
<security:logout logout-success-url="/" delete-cookies="JSESSIONID"/>
<security:remember-me user-service-ref="enterpriseAuthenticationProvider"/>
<security:session-management invalid-session-url="/">
<security:concurrency-control max-sessions="2" error-if-maximum-exceeded="true" />
</security:session-management>
</security:http>
<security:http pattern="/**" auto-config="false" use-expressions="true" authentication-manager-ref="autenticationManagerUser">
<security:intercept-url pattern="/**" access="permitAll" />
<security:form-login login-page="/login" default-target-url="/" authentication-failure-url="/login_error" />
<security:logout logout-success-url="/" delete-cookies="JSESSIONID"/>
<security:remember-me user-service-ref="UserAuthenticationProvider"/>
<security:session-management invalid-session-url="/">
<security:concurrency-control max-sessions="2" error-if-maximum-exceeded="true" />
</security:session-management>
</security:http>
<security:authentication-manager id="autenticationManagerUserEnterprise">
<security:authentication-provider user-service-ref="enterpriseAuthenticationProvider">
<security:password-encoder hash="plaintext"></security:password-encoder>
</security:authentication-provider>
</security:authentication-manager>
<security:authentication-manager id="autenticationManagerUser">
<security:authentication-provider user-service-ref="UserAuthenticationProvider">
<security:password-encoder hash="plaintext"></security:password-encoder>
</security:authentication-provider>
</security:authentication-manager>
<bean id="enterpriseAuthenticationProvider" class="com.test.security.enterpriseAuthenticationProvider"></bean>
<bean id="UserAuthenticationProvider" class="com.test.security.UserDetailsServiceImp"></bean>
Then when I go to /enterprise_login form and submit the login data I get a "HTTP 405 - Request method 'POST' not supported" throwed by tomcat in the url /enterprise_login_process (the url configured to act as login-processing-url. I can't figure out where the problem is, any help is really appreciated.
PD: My web.xml looks like:
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name>AT-2</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring-config.xml
</param-value>
</context-param>
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>tutorial.root</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</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>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-config.xml</param-value>
</init-param>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
The issue is that the first configuration currently only matches on URLs that start with "/enterprise/" and the URL to process authentication is configured as "/enterprise_login_process". This means that submitting a POST to "/enterprise_login_process" will submit to the second configuration which is not trying to authenticate "/enterprise_login_process".
To fix this you need to ensure the http#pattern and the login-processing-url are aligned. For example:
<security:http pattern="/enterprise/**"
auto-config="false"
use-expressions="true"
authentication-manager-ref="autenticationManagerUserEnterprise">
<security:intercept-url pattern="/enterprise/login"
access="isAnonymous()" />
<security:intercept-url pattern="/**"
access="hasRole('ROLE_ENTERPRISE')" />
<security:form-login login-page="/enterprise/login"
default-target-url="/"
authentication-failure-url="/enterprise/login?error"
login-processing-url="/enterprise/login_process" />
<security:logout logout-success-url="/"
delete-cookies="JSESSIONID"/>
<security:remember-me
user-service-ref="enterpriseAuthenticationProvider"/>
<security:session-management invalid-session-url="/">
<security:concurrency-control max-sessions="2"
error-if-maximum-exceeded="true" />
</security:session-management>
</security:http>
You will observe that I modified the code to ensure all URLs within the block start with "/enterprise/". This also means that you will need to ensure that your login form for enterprise is updated to POST to "/enterprise/login_process".