在oauth2根据授权码获取accsess token时,通关Debug发现在TokenEndpoint类下的getAccessToken方法内会根据principal去数据库获取client_id,但principal内存储的是当前用户的信息,然后就会报错:Given client ID does not match authenticated client
求大神解答怎么破.
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:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:oauth2="http://www.springframework.org/schema/security/oauth2"
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/oauth2
http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.2.xsd">
<!-- 指定不需要权限过滤的路径 -->
<http pattern="/login.jsp" security="none" />
<http pattern="/aouth/token" create-session="stateless"
authentication-manager-ref="oauth2AuthenticationManager"
entry-point-ref="oauth2AuthenticationEntryPoint">
<!-- 设置拦截地址和规则 -->
<intercept-url pattern="/aouth/token" access="IS_AUTHENTICATED_FULLY" />
<!-- 非匿名 -->
<anonymous enabled="false" />
<http-basic entry-point-ref="oauth2AuthenticationEntryPoint" />
<!-- 设置过滤链 -->
<custom-filter ref="clientCredentialsTokenEndpointFilter"
before="BASIC_AUTH_FILTER" />
<!-- 拒绝访问处理 -->
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<!--一个自定义的filter,必须包含authenticationManager,accessDecisionManager,securityMetadataSource三个属性,
我们的所有控制将在这三个类中实现 -->
<beans:bean id="myFilter"
class="com.yichi.mvcm.filter.MyFilterSecurityInterceptor">
<beans:property name="authenticationManager" ref="authenticationManager" />
<beans:property name="accessDecisionManager" ref="myAccessDecisionManagerBean" />
<beans:property name="securityMetadataSource"
ref="myInvocationSecurityMetadataSource" />
</beans:bean>
<!-- 认证客户端的manager -->
<authentication-manager id="oauth2AuthenticationManager">
<authentication-provider user-service-ref="oauth2ClientDetailsUserService" />
</authentication-manager>
<!-- spring security提供的用户登录验证 ,alias的值对应上面的ref="authenticationManager" -->
<authentication-manager alias="authenticationManager">
<!--userDetailServiceImpl 获取登录的用户、用户权限 -->
<authentication-provider user-service-ref="myUserDetailService" />
<!-- 缓存 -->
<!-- <authentication-provider user-service-ref="cachingUserDetailsService"
/> -->
</authentication-manager>
<!-- 缓存 -->
<!-- <beans:bean id="cachingUserDetailsService" class="org.springframework.security.config.authentication.CachingUserDetailsService">
<beans:constructor-arg ref="myUserDetailService" /> 缓存UserDetails的UserCache
<beans:property name="userCache" ref="userCache"/> </beans:bean> <beans:bean
id="userCache" class="org.springframework.security.core.userdetails.cache.EhCacheBasedUserCache">
用于真正缓存的Ehcache对象 <beans:property name="cache" ref="ehcache4UserDetails"></beans:property>
</beans:bean> <beans:bean id="ehcache4UserDetails" class="org.springframework.cache.ehcache.EhCacheFactoryBean"
/> -->
<!--在这个类中,你就可以从数据库中读入用户的密码,角色信息,是否锁定,账号是否过期等 -->
<beans:bean id="myUserDetailService" class="com.yichi.mvcm.filter.MyUserDetailService">
<!-- 配置成员变量 -->
<beans:property name="sysUserService" ref="sysUserService" />
</beans:bean>
<!--访问决策器,决定某个用户具有的角色,是否有足够的权限去访问某个资源 -->
<beans:bean id="myAccessDecisionManagerBean"
class="com.yichi.mvcm.filter.MyAccessDecisionManager">
</beans:bean>
<beans:bean id="sysResService" class="com.yichi.mvcm.service.sys.SysResService"></beans:bean>
<!--资源源数据定义,将所有的资源和权限对应关系建立起来,即定义某一资源可以被哪些角色访问 -->
<beans:bean id="myInvocationSecurityMetadataSource"
class="com.yichi.mvcm.filter.MyInvocationSecurityMetadataSource">
<!-- 配置成员变量 -->
<beans:constructor-arg>
<beans:ref bean="sysResService" />
</beans:constructor-arg>
</beans:bean>
<!-- 配置client客户端信息 -->
<authentication-manager id="clientAuthenticationManager">
<authentication-provider user-service-ref="oauth2ClientDetailsUserService" />
</authentication-manager>
<beans:bean id="oauth2ClientDetailsUserService"
class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<beans:constructor-arg ref="clientDetailsService" />
</beans:bean>
<!-- 数据库读取客户端信息 -->
<beans:bean id="clientDetailsService" class="com.yichi.mvcm.filter.CustomJdbcClientDetailsService">
<beans:constructor-arg index="0" ref="dataSource" /> </beans:bean>
<!-- 资源filter配置 -->
<oauth2:resource-server id="picResourceServer"
resource-id="pic-resource" token-services-ref="tokenServices" />
<!-- 配token service用于生成访问令牌token -->
<beans:bean id="tokenServices"
class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
<beans:property name="tokenStore" ref="tokenStore" />
<!-- 是否生成更新令牌 默认为false -->
<beans:property name="supportRefreshToken" value="true" />
<beans:property name="clientDetailsService" ref="clientDetailsService" />
</beans:bean>
<!-- token仓库 可以选择存储在内存或者数据库 -->
<!-- <beans:bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore">
</beans:bean> -->
<beans:bean id="tokenStore"
class="org.springframework.security.oauth2.provider.token.store.JdbcTokenStore">
<beans:constructor-arg index="0" ref="dataSource" />
</beans:bean>
<!-- 资源 -->
<http pattern="/mvcm/**" create-session="never"
entry-point-ref="oauth2AuthenticationEntryPoint"
access-decision-manager-ref="oauth2AccessDecisionManager">
<anonymous enabled="false" />
<intercept-url pattern="/mvcm/**" access="ROLE_index,SCOPE_READ" />
<custom-filter ref="picResourceServer" before="PRE_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<beans:bean id="oauth2AuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint" />
<beans:bean id="oauthAccessDeniedHandler"
class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" />
<beans:bean id="oauth2AccessDecisionManager"
class="org.springframework.security.access.vote.UnanimousBased">
<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>
<!-- user-approval-page:用户第三方登录认证以后的授权确认页面 error-page : 客户端申请授权的数据与服务端的不相同时跳转的页面 -->
<oauth2:authorization-server
client-details-service-ref="clientDetailsService" token-services-ref="tokenServices"
user-approval-handler-ref="oauthUserApprovalHandler"
user-approval-page="oauth_approval" error-page="oauth_error">
<oauth2:authorization-code
authorization-code-services-ref="authorizationCodeServices" />
<oauth2:implicit />
<oauth2:refresh-token />
<oauth2:client-credentials />
<oauth2:password />
</oauth2:authorization-server>
<!-- 授权码存储到数据库 -->
<beans:bean id="authorizationCodeServices"
class="org.springframework.security.oauth2.provider.code.JdbcAuthorizationCodeServices">
<beans:constructor-arg index="0" ref="dataSource" />
</beans:bean>
<beans:bean id="oauthUserApprovalHandler"
class="org.springframework.security.oauth2.provider.approval.DefaultUserApprovalHandler" />
<!-- <beans:bean id="clientCredentialsTokenEndpointFilter"
class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
<beans:property name="authenticationManager" ref="clientAuthenticationManager" />
</beans:bean> -->
<beans:bean id="clientCredentialsTokenEndpointFilter"
class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
<beans:property name="authenticationManager" ref="clientAuthenticationManager" />
</beans:bean>
<http auto-config="true" use-expressions="true">
<!-- 没有权限时跳转的页面 -->
<access-denied-handler error-page="/accessDenied.jsp" />
<!-- 使用自定义的登录页面 login_page:指定登录页面 authentication-failure-url:登录失败跳转到/login.jsp
login-processing-url进行认证拦截的请求路径 username-parameter和 password-parameter指定属性name字段
default-target-url认证成功默认跳转页面 -->
<form-login login-page="/login.jsp"
authentication-failure-url="/login.jsp?error=1" login-processing-url="/springSecurity"
username-parameter="account" password-parameter="password"
default-target-url="/index.jsp" />
<intercept-url pattern="/oauth/**" access="hasRole('ROLE_userOrg')" />
<!-- 设置单用户登录 -->
<session-management>
<!-- max-sessions表示最多允许多少次重复登录。如果没有配置error-if-maximum-exceeded, 那么用户账号的第二次登录会使第一次登录失效,而配置了的话,那么第二次登录会被阻止。
通常的做法是阻止第二次登录。 -->
<concurrency-control max-sessions="1"
error-if-maximum-exceeded="false" />
</session-management>
<custom-filter ref="myFilter" before="FILTER_SECURITY_INTERCEPTOR" />
<!-- 检测失效的sessionId,session超时时,定位到另外一个URL -->
<session-management invalid-session-url="/login.jsp" />
<logout invalidate-session="true" logout-success-url="/"
logout-url="/logout" />
</http>
</beans:beans>