Spring Oauth2无效的访问令牌
Posted
技术标签:
【中文标题】Spring Oauth2无效的访问令牌【英文标题】:Spring Oauth2 Invalid access token 【发布时间】:2019-03-13 14:58:30 【问题描述】:我有 spring 和 oauth2 的项目,我可以获得令牌,但是当我尝试在受保护的服务中使用它时,我得到响应“无效的访问令牌”。 缺什么?
这是我的调度器 servlet:
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:oauth="http://www.springframework.org/schema/security/oauth2"
xmlns:sec="http://www.springframework.org/schema/security"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="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.2.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<context:component-scan base-package="com.mx.testing.mem.back" />
<sec:http pattern="/oauth/token" create-session="stateless" authentication-manager-ref="authenticationManager">
<sec:intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY" />
<sec:anonymous enabled="false" />
<sec:http-basic entry-point-ref="clientAuthenticationEntryPoint" />
<sec:custom-filter ref="clientCredentialsTokenEndpointFilter" before="BASIC_AUTH_FILTER" />
<sec:access-denied-handler ref="oauthAccessDeniedHandler" />
</sec:http>
<sec:http pattern="/protected/**" create-session="never" entry-point-ref="oauthAuthenticationEntryPoint">
<sec:anonymous enabled="false" />
<sec:intercept-url pattern="/protected/**" method="GET" access="IS_AUTHENTICATED_FULLY" />
<sec:custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
<sec:access-denied-handler ref="oauthAccessDeniedHandler" />
</sec:http>
<bean id="oauthAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
</bean>
<bean id="clientAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="springsec/client" />
<property name="typeName" value="Basic" />
</bean>
<bean id="oauthAccessDeniedHandler"
class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler">
</bean>
<bean id="clientCredentialsTokenEndpointFilter"
class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
<property name="authenticationManager" ref="authenticationManager" />
</bean>
<sec:authentication-manager alias="authenticationManager">
<sec:authentication-provider user-service-ref="clientDetailsUserService" />
</sec:authentication-manager>
<bean id="clientDetailsUserService"
class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<constructor-arg ref="clientDetails" />
</bean>
<bean id="clientDetails" class="com.mx.testing.mem.back.controller.GuestServiceImpl">
<property name="id" value="testingTrustedClient" />
<property name="secretKey" value="testingKeyTrusted" />
</bean>
<sec:authentication-manager id="userAuthenticationManager">
<sec:authentication-provider ref="customUserAuthenticationProvider" />
</sec:authentication-manager>
<bean id="customUserAuthenticationProvider"
class="com.mx.testing.mem.back.controller.UserAuthenticationProvider">
</bean>
<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="userAuthenticationManager"/>
</oauth:authorization-server>
<oauth:resource-server id="resourceServerFilter" resource-id="springsec" token-services-ref="tokenServices" />
<bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore" />
<bean id="tokenServices"
class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
<property name="tokenStore" ref="tokenStore" />
<property name="supportRefreshToken" value="true" />
<property name="accessTokenValiditySeconds" value="12000"></property>
<property name="clientDetailsService" ref="clientDetails" />
</bean>
<!-- Enable @Controller annotation support -->
<mvc:annotation-driven />
<mvc:resources mapping="/assets/**" location="/assets/" />
<mvc:resources mapping="/druid/**" location="/WEB-INF/support/http/resources" />
<!-- <bean id="dataSource"
class="com.alibaba.druid.pool.DruidDataSource"
init-method="init" destroy-method="close">
<property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver" />
<property name="url" value="jdbc:sqlserver://captrade.database.windows.net;database=AgileTrade;" />
<property name="username" value="testing" />
<property name="password" value="C4pgemini2017" />
<property name="validationQuery" value="SELECT 1" />
</bean> -->
<bean id="dataSource" class="oracle.jdbc.pool.OracleDataSource">
<property name="dataSourceName" value="ds"/>
<property name="URL" value="jdbc:oracle:thin:@127.0.0.1:1521:cdb1"/>
<property name="user" value="C##testing_SCHEME"/>
<property name="password" value="testing"/>
</bean>
<bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.mx.testing.mem.back.mapper" />
</bean>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<mvc:default-servlet-handler />
<context:annotation-config/>
</beans>
我的 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"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="verwandlung" version="3.0">
<display-name>testing MX</display-name>
<session-config>
<session-timeout>
3000
</session-timeout>
</session-config>
<!-- Spring MVC Configuration -->
<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>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/dispatcher-servlet.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</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>
<filter>
<filter-name>CorsFilter</filter-name>
<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
<init-param>
<param-name>cors.allowed.origins</param-name>
<param-value>*</param-value>
</init-param>
<init-param>
<param-name>cors.allowed.methods</param-name>
<param-value>GET,POST,HEAD,OPTIONS,PUT</param-value>
</init-param>
<init-param>
<param-name>cors.allowed.headers</param-name>
<param-value>Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers</param-value>
</init-param>
<init-param>
<param-name>cors.exposed.headers</param-name>
<param-value>Access-Control-Allow-Origin,Access-Control-Allow-Credentials</param-value>
</init-param>
<init-param>
<param-name>cors.support.credentials</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>cors.preflight.maxage</param-name>
<param-value>100000</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CorsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Druid -->
<servlet>
<servlet-name>DruidStatView</servlet-name>
<servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DruidStatView</servlet-name>
<url-pattern>/druid/*</url-pattern>
</servlet-mapping>
<!-- Home Page -->
<welcome-file-list>
<welcome-file>/</welcome-file>
</welcome-file-list>
</web-app>
我通过以下方式获得令牌:
http://localhost:8080/ServicesMEM/oauth/token?username=myuser&password=mypassword&grant_type=password&scope=read,write,trust
我得到:
"access_token": "261c2808-9df1-43a6-a6bd-f389a4ed0178",
"token_type": "bearer",
"refresh_token": "e53212b5-3cd3-4286-8833-c78069473d74",
"expires_in": 10673,
"scope": "read,write,trust"
但是当我使用http://localhost:8080/ServicesMEM/protected/demo/hjhh/?access_token=261c2808-9df1-43a6-a6bd-f389a4ed0178
我明白了:
"error": "invalid_token",
"error_description": "Invalid access token: 261c2808-9df1-43a6-a6bd-f389a4ed0178"
我使用 Header : Authorization Bearer ACCESS_TOKEN 但我得到同样的错误。 我错过了什么?
【问题讨论】:
【参考方案1】:答案:
我需要将 MemoryToken Store 更改为 JDBC 令牌存储:
只需将 inMemoryTokenStore 替换为 JDBCTokenStore:
<bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.store.JdbcTokenStore">
<constructor-arg name="dataSource" ref="dataSource" />
</bean>
并在数据库中为 Oauth2 创建表:
create table oauth_access_token(
token_id varchar2(100),
token BLOB,
authentication_id varchar2(100),
user_name varchar2(100),
client_id varchar2(100),
authentication BLOB,
refresh_token varchar2(4000),
primary key(token_id)
);
create table oauth_refresh_token(
token_id varchar2(100),
token BLOB,
authentication BLOB
);
【讨论】:
以上是关于Spring Oauth2无效的访问令牌的主要内容,如果未能解决你的问题,请参考以下文章
spring security oauth2 (2.0.8) 使用 InMemory tokenstore 获取无效访问令牌
尝试使用spring oauth2中的刷新令牌获取新的访问令牌时出现无效的客户端错误
Spring Security Oauth2 客户端获取访问令牌失败,请求代码无效=415,消息=不支持的媒体类型
oauth2 spring security with spring session 使那些不活动 30 分钟的用户无效