spring security oauth2 (2.0.8) 使用 InMemory tokenstore 获取无效访问令牌
Posted
技术标签:
【中文标题】spring security oauth2 (2.0.8) 使用 InMemory tokenstore 获取无效访问令牌【英文标题】:spring security oauth2 (2.0.8) getting Invalid access token used InMemory tokenstore 【发布时间】:2016-05-04 00:45:53 【问题描述】:尝试在我的应用程序中实现 spring security oauth2。
我可以使用以下方法获取访问令牌和刷新令牌:
http://localhost:8080/xApp/oauth/token?username=user1&password=password&grant_type=password&client_id=xApp&client_secret=xApp
“access_token”:“798c7e71-983b-4137-a0cb-ceae4e9b4190” “token_type”:“承载者” “刷新令牌”:“0752b8ff-5086-4457-918d-54376c7a2bec” “过期”:299 “范围”:“读取信任写入”
当我尝试使用以下 url 访问受保护的资源时
http://localhost:8080/xapp/data/product/api/index/?access_token=798c7e71-983b-4137-a0cb-ceae4e9b4190
我得到:
“错误”:“无效令牌” “error_description”:“无效的访问令牌:db48214c-04d7-4d6b-aa34-6d16c9c2a438”
applicationContext-security.xml:
<?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:oauth="http://www.springframework.org/schema/security/oauth2"
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.2.xsd
http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2.xsd">
<http pattern="/login*" security="none" />
<http pattern="/*.html" security="none" />
<http pattern="/*.pdf" security="none" />
<http pattern="/*.xls" security="none" />
<http pattern="/cache-viewer.jnlp" security="none" />
<!-- /old documentation URLs -->
<!-- servlets -->
<http pattern="/Index" security="none" />
<http pattern="/ServletRedirector" security="none" />
<!-- This is where we tells spring security what URL should be protected
and what roles have access to them -->
<http pattern="/data/**" entry-point-ref="oauthAuthenticationEntryPoint"
create-session="never" xmlns="http://www.springframework.org/schema/security"
use-expressions="true">
<anonymous enabled="false" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
<custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
</http>
<http pattern="/oauth/token" create-session="stateless"
use-expressions="true">
<!-- authentication-manager-ref="clientAuthenticationManager" -->
<intercept-url pattern="/oauth/token" access="hasRole('Administrator')" />
<anonymous enabled="false" />
<custom-filter ref="clientCredentialsTokenEndpointFilter"
after="BASIC_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
<http-basic entry-point-ref="clientAuthenticationEntryPoint" />
</http>
<http use-expressions="true" disable-url-rewriting="true" entry-point-ref="authenticationChooser">
<!-- /servlets -->
<intercept-url pattern="/**" access="isAuthenticated()" />
<intercept-url pattern="/" access="isAuthenticated()" />
<form-login login-page="/login" authentication-failure-url="/login?login_error=1" authentication-success-handler-ref="authSuccessHandler"/>
<logout logout-url="/logout" logout-success-url="/login" />
<remember-me key="XappWebClient" services-ref="rememberMeServices" />
<custom-filter ref="jbossSecurityFilter" after="REMEMBER_ME_FILTER" />
</http>
<beans:bean id="oauthAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<beans:property name="realmName" value="Xapp" />
</beans:bean>
<beans:bean id="clientAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<beans:property name="realmName" value="Xapp" />
<beans:property name="typeName" value="Basic" />
</beans:bean>
<beans:bean id="oauthAccessDeniedHandler"
class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" />
<beans:bean id="clientCredentialsTokenEndpointFilter"
class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
<beans:property name="authenticationManager" ref="clientAuthenticationManager" />
</beans:bean>
<beans:bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased"
xmlns="http://www.springframework.org/schema/beans">
<beans:constructor-arg>
<beans:list>
<beans:bean class="org.springframework.security.oauth2.provider.vote.ScopeVoter"/>
<beans:bean class="org.springframework.security.access.vote.RoleVoter"/>
<beans:bean class="org.springframework.security.access.vote.AuthenticatedVoter"/>
</beans:list>
</beans:constructor-arg>
</beans:bean>
<authentication-manager id="clientAuthenticationManager"
xmlns="http://www.springframework.org/schema/security">
<authentication-provider user-service-ref="clientDetailsUserService" />
</authentication-manager>
<beans:bean id="clientDetailsUserService"
class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<beans:constructor-arg ref="clientDetails" />
</beans:bean>
<!-- This defined token store, we have used inmemory tokenstore for now
but this can be changed to a user defined one -->
<beans:bean id="tokenStore"
class="org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore" />
<!-- This is where we defined token based configurations, token validity
and other things -->
<beans:bean id="tokenServices"
class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
<beans:property name="tokenStore" ref="tokenStore" />
<beans:property name="supportRefreshToken" value="true" />
<beans:property name="accessTokenValiditySeconds" value="300000"/>
<beans:property name="clientDetailsService" ref="clientDetails" />
</beans:bean>
<beans:bean id="userApprovalHandler"
class="org.springframework.security.oauth2.provider.approval.TokenStoreUserApprovalHandler">
<beans:property name="tokenStore" ref="tokenStore" />
<beans:property name="requestFactory" ref="oAuth2RequestFactory" />
</beans:bean>
<beans:bean id="oAuth2RequestFactory"
class="org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory">
<beans:constructor-arg ref="clientDetails" />
</beans:bean>
<beans:bean id="approvalStore" class="org.springframework.security.oauth2.provider.approval.TokenApprovalStore">
<beans:property name="tokenStore" ref="tokenStore"/>
</beans:bean>
<!-- OAuth2 Authorization Server -->
<oauth:authorization-server client-details-service-ref="clientDetails"
token-services-ref="tokenServices"
user-approval-handler-ref="userApprovalHandler">
<oauth:authorization-code/>
<oauth:implicit/>
<oauth:refresh-token/>
<oauth:client-credentials/>
<oauth:password authentication-manager-ref="authenticationManager"/>
</oauth:authorization-server>
<oauth:resource-server id="resourceServerFilter"
resource-id="Xapp" token-services-ref="tokenServices" />
<oauth:client-details-service id="clientDetails">
<!-- client -->
<oauth:client client-id="Xapp"
authorized-grant-types="password,authorization_code,refresh_token,implicit"
secret="Xapp" scope="read,write,trust" authorities="Administrator" access-token-validity="300" refresh-token-validity="600"/>
</oauth:client-details-service>
<authentication-manager alias="authenticationManager">
<authentication-provider ref="jaasAuthenticationProvider"/>
</authentication-manager>
<beans:bean id="rememberMeServices"
class="com.Xapp.Xapp.web.authentication.rememberme.RememberMeServices">
<beans:property name="userDetailsService" ref="userDetailsService" />
<beans:property name="key" value="XappWebClient" />
</beans:bean>
<beans:bean id="jaasNameCallBackHandler"
class="com.Xapp.Xapp.web.authentication.XappNameCallbackHandler">
<beans:property name="userDetailsService" ref="userDetailsService" />
<beans:property name="callbackHandler">
<beans:bean class="org.springframework.security.authentication.jaas.JaasNameCallbackHandler"/>
</beans:property>
</beans:bean>
<beans:bean id="jaasAuthenticationProvider"
class="org.springframework.security.authentication.jaas.JaasAuthenticationProvider">
<beans:property name="refreshConfigurationOnStartup" value="false"/>
<beans:property name="loginConfig" value="/WEB-INF/login.conf" />
<beans:property name="loginContextName" value="Xapp" />
<beans:property name="callbackHandlers">
<beans:list>
<beans:ref bean="jaasNameCallBackHandler" />
<beans:bean class="org.springframework.security.authentication.jaas.JaasPasswordCallbackHandler" />
</beans:list>
</beans:property>
<beans:property name="authorityGranters">
<beans:list>
<beans:bean class="com.Xapp.Xapp.web.authentication.XappAuthorityGranter" />
</beans:list>
</beans:property>
</beans:bean>
<beans:bean id="userDetailsService" class="com.Xapp.Xapp.web.authentication.XappUserDetailsService">
</beans:bean>
<beans:bean id="jbossSecurityFilter" class="com.Xapp.Xapp.web.authentication.JBossSecurityFilter">
<beans:property name="clientLoginDomain" value="client-login" />
<beans:property name="callbackHandler">
<beans:bean class="com.Xapp.Xapp.web.authentication.SecurityContextHolderAwareCallbackHandler" />
</beans:property>
</beans:bean>
<beans:bean id="authSuccessHandler"
class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
<beans:property name="redirectStrategy" ref="XappRedirectStrategy"></beans:property>
</beans:bean>
<beans:bean id="XappRedirectStrategy"
class="com.Xapp.Xapp.web.authentication.XappRedirectStrategy">
</beans:bean>
<beans:bean id="formAuthenticationEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<beans:property name="loginFormUrl" value="/login" />
</beans:bean>
<beans:bean id="authenticationChooser" class="org.springframework.security.web.authentication.DelegatingAuthenticationEntryPoint">
<beans:constructor-arg>
<beans:map>
<beans:entry key="#new com.Xapp.Xapp.web.authentication.DataRequestMatcher()" value-ref="oauthAuthenticationEntryPoint" />
</beans:map>
</beans:constructor-arg>
<beans:property name="defaultEntryPoint" ref="formAuthenticationEntryPoint" />
</beans:bean>
</beans:beans>
控制器类路径:
@Controller
@RequestMapping("/data/product")
public final class AppController extends AbstractDataController
@RequestMapping(value = "/index", method = RequestMethod.GET)
@ResponseBody public List<Data> getProducts() throws ServerException
final List<DataTO> dataTOs = productLogic.findDataTOsForCurrentUser();
Collections.sort(dataTOs, HasName.COMPARATOR);
return ListConverter.convert(dataTOs, fromDataTO);
调试第二个请求时的堆栈跟踪 accessTokenStore is not stored access token is empty :
2016-02-02 11:11:16,268 DEBUG [org.springframework.security.web.context.HttpSessionSecurityContextRepository] (default task-3) HttpSession returned null object for SPRING_SECURITY_CONTEXT
2016-02-02 11:11:16,269 DEBUG [org.springframework.security.web.context.HttpSessionSecurityContextRepository] (default task-3) No SecurityContext was available from the HttpSession: io.undertow.servlet.spec.HttpSessionImpl@4439d585. A new one will be created.
2016-02-02 11:11:16,315 DEBUG [org.springframework.security.web.FilterChainProxy] (default task-3) /data/product/index at position 2 of 10 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2016-02-02 11:11:16,315 DEBUG [org.springframework.security.web.FilterChainProxy] (default task-3) /data/product/index at position 3 of 10 in additional filter chain; firing Filter: 'OAuth2AuthenticationProcessingFilter'
2016-02-02 11:11:16,315 DEBUG [org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter] (default task-3) Entering Do filter>>>>>>>>>>>>>>>>>>>>
2016-02-02 11:11:16,316 DEBUG [org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter] (default task-3) !!!!!!!!!!request>>>>>>>>> org.springframework.security.web.context.HttpSessionSecurityContextRepository$Servlet3SaveToSessionRequestWrapper@590ca42d
2016-02-02 11:11:16,317 DEBUG [org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter] (default task-3) !!!!!!!!!!authentication>>>>>>>>> org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken@763c08a: Principal: 34a81f49-528d-4087-b192-414b6e2224b6; Credentials: [PROTECTED]; Authenticated: false; Details: remoteAddress=127.0.0.1, sessionId=<SESSION>, tokenType=BearertokenValue=<TOKEN>; Not granted any authorities
2016-02-02 11:11:16,317 DEBUG [org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationManager] (default task-3) >>>Call authenticate>>>> token 34a81f49-528d-4087-b192-414b6e2224b6
2016-02-02 11:11:16,317 DEBUG [org.springframework.security.oauth2.provider.token.DefaultTokenServices] (default task-3) >>>>>>accessTokenValue>>>>>>>>>>>>>>> 34a81f49-528d-4087-b192-414b6e2224b6
2016-02-02 11:11:16,317 DEBUG [org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore] (default task-3) >>>>MAP>>>>>>>
2016-02-02 11:11:16,317 DEBUG [org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter] (default task-3) <<<<<<<<<<<Trace Error>>>>>>>>>>>>>>>>>>
2016-02-02 11:11:16,339 ERROR [stderr] (default task-3) error="invalid_token", error_description="Invalid access token: 34a81f49-528d-4087-b192-414b6e2224b6"
2016-02-02 11:11:16,339 ERROR [stderr] (default task-3) at org.springframework.security.oauth2.provider.token.DefaultTokenServices.loadAuthentication(DefaultTokenServices.java:237)
2016-02-02 11:11:16,340 ERROR [stderr] (default task-3) at org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationManager.authenticate(OAuth2AuthenticationManager.java:88)
2016-02-02 11:11:16,340 ERROR [stderr] (default task-3) at org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter.doFilter(OAuth2AuthenticationProcessingFilter.java:152)
2016-02-02 11:11:16,340 ERROR [stderr] (default task-3) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
2016-02-02 11:11:16,340 ERROR [stderr] (default task-3) at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50)
2016-02-02 11:11:16,340 ERROR [stderr] (default task-3) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
2016-02-02 11:11:16,340 ERROR [stderr] (default task-3) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
2016-02-02 11:11:16,340 ERROR [stderr] (default task-3) at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
2016-02-02 11:11:16,340 ERROR [stderr] (default task-3) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
2016-02-02 11:11:16,340 ERROR [stderr] (default task-3) at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
可能与Oauth2: Invalid access token 重复,但未得到答复。尝试堆栈中的其他链接无法解决我的问题。任何有关配置 OAuth2 Spring security 2.0.8 的帮助或建议都会很棒。
我们可以使用下面答案中发布的 JDBCtokenstore 和 jwttokenstore 进行配置,但仍然无法使用 InMemorystore 对此有任何帮助!!!
【问题讨论】:
【参考方案1】:从资源 API 看来,您在请求参数中传递了 access_token。您必须像这样在请求标头中传递 access_token :
Authorization: Bearer <access_token>
cURL 示例:
curl -X GET -H "Authorization: Bearer 89af6541-f87f-4c63-be6d-6012426bb745" -H "Cache-Control: no-cache" "http://localhost:8080/xapp/data/product/api/index"
【讨论】:
【参考方案2】:解决无效的访问令牌:
我们将存储类型从 InMemory 更改为数据库存储 (JdbcTokenStore)。
为所有应该在 applicationContext-security.xml 中保护 spring 安全 URL 的 http 标签添加了 rememberMeServices。
<remember-me key="xAppWebClient" services-ref="rememberMeServices" />
<custom-filter ref="jbossSecurityFilter" after="REMEMBER_ME_FILTER" />
applicationContext-security.xml 更改:
<?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:oauth="http://www.springframework.org/schema/security/oauth2"
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.2.xsd
http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2.xsd">
<http pattern="/Index" security="none" />
<!--This is where we tells spring security what URL should be protected
and what roles have access to them -->
<http pattern="/data/**" entry-point-ref="oauthAuthenticationEntryPoint"
create-session="never" xmlns="http://www.springframework.org/schema/security"
use-expressions="true">
<anonymous enabled="false" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
<intercept-url pattern="/data/**" access="isAuthenticated()" />
<remember-me key="XappWebClient" services-ref="rememberMeServices" />
<custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
<custom-filter ref="jbossSecurityFilter" after="REMEMBER_ME_FILTER" />
</http>
<http pattern="/oauth/token" create-session="stateless"
use-expressions="true" authentication-manager-ref="authenticationManager">
<intercept-url pattern="/oauth/token" access="isAuthenticated()" />
<anonymous enabled="false" />
<custom-filter ref="clientCredentialsTokenEndpointFilter"
before="BASIC_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
<http-basic entry-point-ref="clientAuthenticationEntryPoint" />
<remember-me key="XappWebClient" services-ref="rememberMeServices" />
<custom-filter ref="jbossSecurityFilter" after="REMEMBER_ME_FILTER" />
</http>
<http use-expressions="true" disable-url-rewriting="true" entry-point-ref="authenticationChooser">
<!-- /servlets -->
<intercept-url pattern="/**" access="isAuthenticated()" />
<intercept-url pattern="/" access="isAuthenticated()" />
<form-login login-page="/login" authentication-failure-url="/login?login_error=1" authentication-success-handler-ref="authSuccessHandler"/>
<logout logout-url="/logout" logout-success-url="/login" />
<remember-me key="XappWebClient" services-ref="rememberMeServices" />
<custom-filter ref="jbossSecurityFilter" after="REMEMBER_ME_FILTER" />
</http>
<beans:bean id="oauthAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<beans:property name="realmName" value="Xapp" />
</beans:bean>
<beans:bean id="clientAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<beans:property name="typeName" value="Basic" />
</beans:bean>
<beans:bean id="oauthAccessDeniedHandler"
class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" />
<beans:bean id="clientCredentialsTokenEndpointFilter"
class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
<beans:property name="authenticationManager" ref="authenticationManager" />
</beans:bean>
<beans:bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased"
xmlns="http://www.springframework.org/schema/beans">
<beans:constructor-arg>
<beans:list>
<beans:bean class="org.springframework.security.oauth2.provider.vote.ScopeVoter"/>
<beans:bean class="org.springframework.security.access.vote.RoleVoter"/>
<beans:bean class="org.springframework.security.access.vote.AuthenticatedVoter"/>
</beans:list>
</beans:constructor-arg>
</beans:bean>
<beans:bean id="clientDetailsUserService"
class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<beans:constructor-arg ref="clientDetails" />
</beans:bean>
<!-- This defined token store, we have used JdbcTokenStore insted of inmemory tokenstore-->
<beans:bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.store.JdbcTokenStore">
<beans:constructor-arg name="dataSource" ref="dataSource" />
</beans:bean>
<beans:bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<beans:property name="jndiName">
<beans:value>jdbc/XappDS</beans:value>
</beans:property>
</beans:bean>
<!-- This is where we defined token based configurations, token validity
and other things -->
<beans:bean id="tokenServices"
class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
<beans:property name="tokenStore" ref="tokenStore" />
<beans:property name="supportRefreshToken" value="true" />
<beans:property name="clientDetailsService" ref="clientDetails" />
</beans:bean>
<beans:bean id="userApprovalHandler"
class="org.springframework.security.oauth2.provider.approval.TokenStoreUserApprovalHandler">
<beans:property name="tokenStore" ref="tokenStore" />
<beans:property name="requestFactory" ref="oAuth2RequestFactory" />
</beans:bean>
<beans:bean id="oAuth2RequestFactory"
class="org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory">
<beans:constructor-arg ref="clientDetails" />
</beans:bean>
<beans:bean id="approvalStore" class="org.springframework.security.oauth2.provider.approval.TokenApprovalStore">
<beans:property name="tokenStore" ref="tokenStore"/>
</beans:bean>
<!-- OAuth2 Authorization Server -->
<oauth:authorization-server client-details-service-ref="clientDetails"
token-services-ref="tokenServices"
user-approval-handler-ref="userApprovalHandler">
<oauth:authorization-code/>
<oauth:implicit/>
<oauth:refresh-token/>
<oauth:client-credentials/>
<oauth:password authentication-manager-ref="authenticationManager"/>
</oauth:authorization-server>
<oauth:resource-server id="resourceServerFilter"
token-services-ref="tokenServices" />
<oauth:client-details-service id="clientDetails">
<oauth:client client-id="Xapp"
authorized-grant-types="password,authorization_code,refresh_token,implicit"
secret="Xapp" scope="read,write,trust" authorities="Administrator" access-token-validity="300" refresh-token-validity="600"/>
</oauth:client-details-service>
<authentication-manager alias="authenticationManager">
<authentication-provider ref="jaasAuthenticationProvider" />
<authentication-provider user-service-ref="clientDetailsUserService"/>
</authentication-manager>
<beans:bean id="rememberMeServices"
class="com.Xapp.Xapp.web.authentication.rememberme.RememberMeServices">
<beans:property name="userDetailsService" ref="userDetailsService" />
<beans:property name="key" value="XappWebClient" />
</beans:bean>
<beans:bean id="jaasNameCallBackHandler"
class="com.Xapp.Xapp.web.authentication.XappNameCallbackHandler">
<beans:property name="userDetailsService" ref="userDetailsService" />
<beans:property name="callbackHandler">
<beans:bean class="org.springframework.security.authentication.jaas.JaasNameCallbackHandler"/>
</beans:property>
</beans:bean>
<beans:bean id="jaasAuthenticationProvider"
class="org.springframework.security.authentication.jaas.JaasAuthenticationProvider">
<beans:property name="refreshConfigurationOnStartup" value="false"/>
<beans:property name="loginConfig" value="/WEB-INF/login.conf" />
<beans:property name="loginContextName" value="Xapp" />
<beans:property name="callbackHandlers">
<beans:list>
<beans:ref bean="jaasNameCallBackHandler" />
<beans:bean class="org.springframework.security.authentication.jaas.JaasPasswordCallbackHandler" />
</beans:list>
</beans:property>
<beans:property name="authorityGranters">
<beans:list>
<beans:bean class="com.Xapp.Xapp.web.authentication.XappAuthorityGranter" />
</beans:list>
</beans:property>
</beans:bean>
<beans:bean id="userDetailsService" class="com.Xapp.Xapp.web.authentication.XappUserDetailsService">
</beans:bean>
<beans:bean id="jbossSecurityFilter" class="com.Xapp.Xapp.web.authentication.JBossSecurityFilter">
<beans:property name="clientLoginDomain" value="client-login" />
<beans:property name="callbackHandler">
<beans:bean class="com.Xapp.Xapp.web.authentication.SecurityContextHolderAwareCallbackHandler" />
</beans:property>
</beans:bean>
<beans:bean id="authSuccessHandler"
class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
<beans:property name="redirectStrategy" ref="XappRedirectStrategy"></beans:property>
</beans:bean>
<beans:bean id="XappRedirectStrategy"
class="com.Xapp.Xapp.web.authentication.XappRedirectStrategy">
</beans:bean>
<beans:bean id="formAuthenticationEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<beans:property name="loginFormUrl" value="/login" />
</beans:bean>
<beans:bean id="authenticationChooser" class="org.springframework.security.web.authentication.DelegatingAuthenticationEntryPoint">
<beans:constructor-arg>
<beans:map>
<beans:entry key="#new com.Xapp.Xapp.web.authentication.DataRequestMatcher()" value-ref="oauthAuthenticationEntryPoint" />
</beans:map>
</beans:constructor-arg>
<beans:property name="defaultEntryPoint" ref="formAuthenticationEntryPoint" />
</beans:bean>
</beans:beans>
我们尝试的另一种方法是使用 JwtTokenStore,它是内存的绝佳替代品。像xml一样配置:
<http pattern="/login*" security="none" />
<http pattern="/*.html" security="none" />
<http pattern="/*.pdf" security="none" />
<http pattern="/Index" security="none" />
<!-- This is where we tells spring security what URL should be protected
and what roles have access to them -->
<http pattern="/restdata/**" entry-point-ref="oauthAuthenticationEntryPoint"
create-session="stateless" xmlns="http://www.springframework.org/schema/security"
use-expressions="true">
<anonymous enabled="false" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
<intercept-url pattern="/restdata/**" access="isAuthenticated()" />
<remember-me key="XappWebClient" services-ref="rememberMeServices" />
<custom-filter ref="jbossSecurityFilter" after="REMEMBER_ME_FILTER" />
<custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
</http>
<http pattern="/oauth/token" create-session="stateless"
use-expressions="true" authentication-manager-ref="authenticationManager">
<intercept-url pattern="/oauth/token" access="isAuthenticated()" />
<anonymous enabled="false" />
<custom-filter ref="clientCredentialsTokenEndpointFilter"
before="BASIC_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
<http-basic entry-point-ref="clientAuthenticationEntryPoint" />
<remember-me key="XappWebClient" services-ref="rememberMeServices" />
<custom-filter ref="jbossSecurityFilter" after="REMEMBER_ME_FILTER" />
</http>
<http use-expressions="true" disable-url-rewriting="true"
entry-point-ref="authenticationChooser">
<intercept-url pattern="/**" access="isAuthenticated()" />
<intercept-url pattern="/" access="isAuthenticated()" />
<form-login login-page="/login" authentication-failure-url="/login?login_error=1"
authentication-success-handler-ref="authSuccessHandler" />
<logout logout-url="/logout" logout-success-url="/login" />
<remember-me key="XappWebClient" services-ref="rememberMeServices" />
<custom-filter ref="jbossSecurityFilter" after="REMEMBER_ME_FILTER" />
<custom-filter ref="myFilter" position="PRE_AUTH_FILTER" /> <!--Custom filter intercepts the login request from web client and authorize the user using oauth token request-->
</http>
<beans:bean id="myFilter"
class="com.Xapp.Xapp.web.authentication.XappPreAuthenticationFilter">
<beans:property name="authenticationManager" ref="authenticationManager" />
</beans:bean>
<beans:bean id="oauthAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<beans:property name="realmName" value="Xapp" />
</beans:bean>
<beans:bean id="clientAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<!-- <beans:property name="realmName" value="Xapp" /> -->
<beans:property name="typeName" value="Basic" />
</beans:bean>
<beans:bean id="oauthAccessDeniedHandler"
class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" />
<beans:bean id="clientCredentialsTokenEndpointFilter"
class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
<beans:property name="authenticationManager" ref="authenticationManager" />
</beans:bean>
<beans:bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased"
xmlns="http://www.springframework.org/schema/beans">
<beans:constructor-arg>
<beans:list>
<beans:bean class="org.springframework.security.oauth2.provider.vote.ScopeVoter"/>
<beans:bean class="org.springframework.security.access.vote.RoleVoter"/>
<beans:bean class="org.springframework.security.access.vote.AuthenticatedVoter"/>
</beans:list>
</beans:constructor-arg>
</beans:bean>
<beans:bean id="clientDetailsUserService"
class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<beans:constructor-arg ref="clientDetails" />
</beans:bean>
<beans:bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.store.JwtTokenStore">
<beans:constructor-arg ref="jwtTokenEnhancer" />
</beans:bean>
<beans:bean id="jwtTokenEnhancer" class="org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter">
<beans:property name="signingKey" value="Xapp" />
<beans:property name="accessTokenConverter" ref="tokenConverter" />
</beans:bean>
<!-- define token based configurations, token validity and other things -->
<beans:bean id="tokenServices"
class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
<beans:property name="tokenStore" ref="tokenStore" />
<beans:property name="supportRefreshToken" value="true" />
<beans:property name="clientDetailsService" ref="clientDetails" />
<beans:property name="tokenEnhancer" ref="jwtTokenEnhancer" />
</beans:bean>
<beans:bean id="userApprovalHandler"
class="org.springframework.security.oauth2.provider.approval.TokenStoreUserApprovalHandler">
<beans:property name="tokenStore" ref="tokenStore" />
<beans:property name="requestFactory" ref="oAuth2RequestFactory" />
</beans:bean>
<beans:bean id="oAuth2RequestFactory"
class="org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory">
<beans:constructor-arg ref="clientDetails" />
</beans:bean>
<beans:bean id="approvalStore" class="org.springframework.security.oauth2.provider.approval.TokenApprovalStore">
<beans:property name="tokenStore" ref="tokenStore"/>
</beans:bean>
<!-- OAuth2 Authorization Server -->
<oauth:authorization-server client-details-service-ref="clientDetails"
token-services-ref="tokenServices"
user-approval-handler-ref="userApprovalHandler">
<oauth:authorization-code/>
<oauth:implicit/>
<oauth:refresh-token/>
<oauth:client-credentials/>
<oauth:password authentication-manager-ref="authenticationManager"/>
</oauth:authorization-server>
<oauth:resource-server id="resourceServerFilter"
token-services-ref="tokenServices" />
<oauth:client-details-service id="clientDetails">
<!-- client -->
<oauth:client client-id="Xapp"
authorized-grant-types="password,authorization_code,refresh_token"
secret="Xapp" scope="read,write,trust" authorities="Administrator"/>
</oauth:client-details-service>
<global-method-security
pre-post-annotations="enabled" proxy-target-class="true">
<expression-handler ref="oauthExpressionHandler" />
</global-method-security>
<oauth:expression-handler id="oauthExpressionHandler" />
<oauth:web-expression-handler id="oauthWebExpressionHandler" />
<authentication-manager alias="authenticationManager">
<authentication-provider ref="jaasAuthenticationProvider" />
<authentication-provider user-service-ref="clientDetailsUserService"/>
</authentication-manager>
【讨论】:
以上是关于spring security oauth2 (2.0.8) 使用 InMemory tokenstore 获取无效访问令牌的主要内容,如果未能解决你的问题,请参考以下文章
使用 spring-session 和 spring-cloud-security 时,OAuth2ClientContext (spring-security-oauth2) 不会保留在 Redis
Spring-Security OAuth2 设置 - 无法找到 oauth2 命名空间处理程序
聊聊spring security oauth2的几个endpoint的认证