我使用spring oauth实现了oauth2.0。它在localhost中完美运行,但当我将其部署到服务器时,在成功获得客户端凭据授权后,我获得了403禁止。
来自localhost的日志:工作正常。返回刷新令牌和访问令牌。
2016-08-15 23:16:06 DEBUG AntPathRequestMatcher:151 - Checking match of request : '/oauth/token'; against '/oauth/token'
2016-08-15 23:16:06 DEBUG FilterChainProxy:324 - /oauth/token?grant_type=password&client_id=my-trusted-client&username=manju&password=123456 at position 1 of 8 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2016-08-15 23:16:06 DEBUG FilterChainProxy:324 - /oauth/token?grant_type=password&client_id=my-trusted-client&username=manju&password=123456 at position 2 of 8 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2016-08-15 23:16:06 DEBUG FilterChainProxy:324 - /oauth/token?grant_type=password&client_id=my-trusted-client&username=manju&password=123456 at position 3 of 8 in additional filter chain; firing Filter: 'HeaderWriterFilter'
2016-08-15 23:16:06 DEBUG HstsHeaderWriter:128 - Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@3639a75a
2016-08-15 23:16:06 DEBUG FilterChainProxy:324 - /oauth/token?grant_type=password&client_id=my-trusted-client&username=manju&password=123456 at position 4 of 8 in additional filter chain; firing Filter: 'BasicAuthenticationFilter'
2016-08-15 23:16:06 DEBUG FilterChainProxy:324 - /oauth/token?grant_type=password&client_id=my-trusted-client&username=manju&password=123456 at position 5 of 8 in additional filter chain; firing Filter: 'ClientCredentialsTokenEndpointFilter'
2016-08-15 23:16:06 DEBUG AntPathRequestMatcher:151 - Checking match of request : '/oauth/token'; against '/oauth/token'
2016-08-15 23:16:06 DEBUG ClientCredentialsTokenEndpointFilter:211 - Request is to process authentication
2016-08-15 23:16:06 DEBUG ProviderManager:162 - Authentication attempt using org.springframework.security.authentication.dao.DaoAuthenticationProvider
2016-08-15 23:16:06 DEBUG ClientCredentialsTokenEndpointFilter:317 - Authentication success. Updating SecurityContextHolder to contain: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@7e8cecce: Principal: org.springframework.security.core.userdetails.User@776427a2: Username: my-trusted-client; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_CLIENT,ROLE_TRUSTED_CLIENT; Credentials: [PROTECTED]; Authenticated: true; Details: null; Granted Authorities: ROLE_CLIENT, ROLE_TRUSTED_CLIENT
2016-08-15 23:16:06 DEBUG FilterChainProxy:324 - /oauth/token?grant_type=password&client_id=my-trusted-client&username=manju&password=123456 at position 6 of 8 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
2016-08-15 23:16:06 DEBUG FilterChainProxy:324 - /oauth/token?grant_type=password&client_id=my-trusted-client&username=manju&password=123456 at position 7 of 8 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
2016-08-15 23:16:06 DEBUG FilterChainProxy:324 - /oauth/token?grant_type=password&client_id=my-trusted-client&username=manju&password=123456 at position 8 of 8 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
2016-08-15 23:16:06 DEBUG AntPathRequestMatcher:151 - Checking match of request : '/oauth/token'; against '/oauth/token'
2016-08-15 23:16:06 DEBUG FilterSecurityInterceptor:218 - Secure object: FilterInvocation: URL: /oauth/token?grant_type=password&client_id=my-trusted-client&username=manju&password=123456; Attributes: [IS_AUTHENTICATED_FULLY]
2016-08-15 23:16:06 DEBUG FilterSecurityInterceptor:347 - Previously Authenticated: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@7e8cecce: Principal: org.springframework.security.core.userdetails.User@776427a2: Username: my-trusted-client; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_CLIENT,ROLE_TRUSTED_CLIENT; Credentials: [PROTECTED]; Authenticated: true; Details: null; Granted Authorities: ROLE_CLIENT, ROLE_TRUSTED_CLIENT
2016-08-15 23:16:06 DEBUG AffirmativeBased:65 - Voter: org.springframework.security.access.vote.RoleVoter@34886fcd, returned: 0
2016-08-15 23:16:06 DEBUG AffirmativeBased:65 - Voter: org.springframework.security.access.vote.AuthenticatedVoter@2a0cac42, returned: 1
2016-08-15 23:16:06 DEBUG FilterSecurityInterceptor:242 - Authorization successful
2016-08-15 23:16:06 DEBUG FilterSecurityInterceptor:255 - RunAsManager did not change Authentication object
2016-08-15 23:16:06 DEBUG FilterChainProxy:309 - /oauth/token?grant_type=password&client_id=my-trusted-client&username=manju&password=123456 reached end of additional filter chain; proceeding with original chain
2016-08-15 23:16:06 DEBUG DispatcherServlet:861 - DispatcherServlet with name 'mvc-dispatcher' processing POST request for [/EWS/oauth/token]
2016-08-15 23:16:06 DEBUG RequestMappingHandlerMapping:306 - Looking up handler method for path /oauth/token
2016-08-15 23:16:06 DEBUG RequestMappingHandlerMapping:316 - Did not find handler method for [/oauth/token]
2016-08-15 23:16:06 DEBUG FrameworkEndpointHandlerMapping:306 - Looking up handler method for path /oauth/token
2016-08-15 23:16:06 DEBUG FrameworkEndpointHandlerMapping:313 - Returning handler method [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]
2016-08-15 23:16:06 DEBUG DefaultListableBeanFactory:251 - Returning cached instance of singleton bean 'oauth2TokenEndpoint'
2016-08-15 23:16:06 DEBUG ResourceOwnerPasswordTokenGranter:63 - Getting access token for: my-trusted-client
2016-08-15 23:16:06 DEBUG ProviderManager:162 - Authentication attempt using org.springframework.security.authentication.dao.DaoAuthenticationProvider
2016-08-15 23:16:06 DEBUG DefaultListableBeanFactory:251 - Returning cached instance of singleton bean 'transactionManager'
部署到云后从服务器记录:抛出403禁止代码。
2016-08-14 14:45:23 DEBUG AntPathRequestMatcher:151 - Checking match of request : '/app/oauth/token'; against '/app/oauth/token'
2016-08-14 14:45:23 DEBUG FilterChainProxy:324 - /app/oauth/token?grant_type=password&client_id=my-trusted-client&username=manju&password=123456 at position 1 of 8 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2016-08-14 14:45:23 DEBUG FilterChainProxy:324 - /app/oauth/token?grant_type=password&client_id=my-trusted-client&username=manju&password=123456 at position 2 of 8 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2016-08-14 14:45:23 DEBUG FilterChainProxy:324 - /app/oauth/token?grant_type=password&client_id=my-trusted-client&username=manju&password=123456 at position 3 of 8 in additional filter chain; firing Filter: 'HeaderWriterFilter'
2016-08-14 14:45:23 DEBUG HstsHeaderWriter:128 - Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@1798528
2016-08-14 14:45:23 DEBUG FilterChainProxy:324 - /app/oauth/token?grant_type=password&client_id=my-trusted-client&username=manju&password=123456 at position 4 of 8 in additional filter chain; firing Filter: 'BasicAuthenticationFilter'
2016-08-14 14:45:23 DEBUG FilterChainProxy:324 - /app/oauth/token?grant_type=password&client_id=my-trusted-client&username=manju&password=123456 at position 5 of 8 in additional filter chain; firing Filter: 'ClientCredentialsTokenEndpointFilter'
2016-08-14 14:45:23 DEBUG AntPathRequestMatcher:151 - Checking match of request : '/app/oauth/token'; against '/app/oauth/token'
2016-08-14 14:45:23 DEBUG ClientCredentialsTokenEndpointFilter:211 - Request is to process authentication
2016-08-14 14:45:23 DEBUG ProviderManager:162 - Authentication attempt using org.springframework.security.authentication.dao.DaoAuthenticationProvider
2016-08-14 14:45:23 DEBUG ClientCredentialsTokenEndpointFilter:317 - Authentication success. Updating SecurityContextHolder to contain: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@7e8cecce: Principal: org.springframework.security.core.userdetails.User@776427a2: Username: my-trusted-client; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_CLIENT,ROLE_TRUSTED_CLIENT; Credentials: [PROTECTED]; Authenticated: true; Details: null; Granted Authorities: ROLE_CLIENT, ROLE_TRUSTED_CLIENT
2016-08-14 14:45:23 DEBUG FilterChainProxy:324 - /app/oauth/token?grant_type=password&client_id=my-trusted-client&username=manju&password=123456 at position 6 of 8 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
2016-08-14 14:45:23 DEBUG FilterChainProxy:324 - /app/oauth/token?grant_type=password&client_id=my-trusted-client&username=manju&password=123456 at position 7 of 8 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
2016-08-14 14:45:23 DEBUG FilterChainProxy:324 - /app/oauth/token?grant_type=password&client_id=my-trusted-client&username=manju&password=123456 at position 8 of 8 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
2016-08-14 14:45:23 DEBUG AntPathRequestMatcher:151 - Checking match of request : '/app/oauth/token'; against '/app/oauth/token'
2016-08-14 14:45:23 DEBUG FilterSecurityInterceptor:218 - Secure object: FilterInvocation: URL: /app/oauth/token?grant_type=password&client_id=my-trusted-client&username=manju&password=123456; Attributes: [IS_AUTHENTICATED_FULLY]
2016-08-14 14:45:23 DEBUG FilterSecurityInterceptor:347 - Previously Authenticated: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@7e8cecce: Principal: org.springframework.security.core.userdetails.User@776427a2: Username: my-trusted-client; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_CLIENT,ROLE_TRUSTED_CLIENT; Credentials: [PROTECTED]; Authenticated: true; Details: null; Granted Authorities: ROLE_CLIENT, ROLE_TRUSTED_CLIENT
2016-08-14 14:45:23 DEBUG AffirmativeBased:65 - Voter: org.springframework.security.access.vote.RoleVoter@f7e452a, returned: 0
2016-08-14 14:45:23 DEBUG AffirmativeBased:65 - Voter: org.springframework.security.access.vote.AuthenticatedVoter@24b0576d, returned: 1
2016-08-14 14:45:23 DEBUG FilterSecurityInterceptor:242 - Authorization successful
2016-08-14 14:45:23 DEBUG FilterSecurityInterceptor:255 - RunAsManager did not change Authentication object
2016-08-14 14:45:23 DEBUG FilterChainProxy:309 - /app/oauth/token?grant_type=password&client_id=my-trusted-client&username=manju&password=123456 reached end of additional filter chain; proceeding with original chain
2016-08-14 14:45:23 DEBUG ExceptionTranslationFilter:116 - Chain processed normally
2016-08-14 14:45:23 DEBUG SecurityContextPersistenceFilter:105 - SecurityContextHolder now cleared, as request processing completed
日志没有说任何关于403错误的信息。它会跳过令牌端点。
注意:我的localhost不是生产服务器都没有SSL。
Spring安全配置文件:
<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"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-4.0.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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<!-- Definition of the Authentication Service -->
<http pattern="/oauth/token" create-session="stateless" authentication-manager-ref="clientAuthenticationManager"
xmlns="http://www.springframework.org/schema/security"
use-expressions="false">
<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"/>
<csrf disabled="true" />
</http>
<!-- Protected resources -->
<http pattern="/rest/**"
create-session="never"
use-expressions="false"
entry-point-ref="oauthAuthenticationEntryPoint"
access-decision-manager-ref="accessDecisionManager"
xmlns="http://www.springframework.org/schema/security">
<anonymous enabled="false"/>
<intercept-url pattern="/rest/**" access="ROLE_USER" />
<custom-filter ref="resourceServerFilter"
before="PRE_AUTH_FILTER"/>
<access-denied-handler
ref="oauthAccessDeniedHandler"/>
<csrf disabled="true" />
</http>
<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"/>
<property name="filterProcessesUrl" value="/oauth/token"/>
</bean>
<bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased"
xmlns="http://www.springframework.org/schema/beans">
<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.web.access.expression.WebExpressionVoter"/>
<bean class="org.springframework.security.access.vote.AuthenticatedVoter"/>
</list>
</constructor-arg>
</bean>
<!-- Authentication in config file -->
<authentication-manager id="clientAuthenticationManager" xmlns="http://www.springframework.org/schema/security">
<authentication-provider user-service-ref="clientDetailsUserService"/>
</authentication-manager>
<authentication-manager alias="authenticationManager"
xmlns="http://www.springframework.org/schema/security">
<authentication-provider user-service-ref="myUserDetailsService">
<password-encoder hash="bcrypt" />
</authentication-provider>
</authentication-manager>
<bean id="clientDetailsUserService"
class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<constructor-arg ref="clientDetails"/>
</bean>
<!-- Token Store in memory
<bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.store.JdbcTokenStore"/>
-->
<bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.store.JdbcTokenStore">
<constructor-arg ref="jdbcTemplate" />
</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="oAuth2RequestFactory" class="org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory">
<constructor-arg ref="clientDetails" />
</bean>
<bean id="userApprovalHandler"
class="org.springframework.security.oauth2.provider.approval.TokenStoreUserApprovalHandler">
<property name="requestFactory" ref="oAuth2RequestFactory" />
<property name="tokenStore" ref="tokenStore" />
</bean>
<!-- Token management -->
<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 />
</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="my-trusted-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="6000"
refresh-token-validity="6000"/>
</oauth:client-details-service>
<!--
<sec:global-method-security pre-post-annotations="enabled" proxy-target-class="true">
<sec:expression-handler ref="oauthExpressionHandler"/>
</sec:global-method-security>
<oauth:expression-handler id="oauthExpressionHandler"/>
<oauth:web-expression-handler id="oauthWebExpressionHandler"/>
-->
<!-- Stateless RESTful service using Basic authentication
<sec:http pattern="/rest/**" create-session="stateless">
<sec:intercept-url pattern='/**' access="hasRole('ROLE_USER')" />
<sec:http-basic />
</sec:http> -->
<!-- enable use-expressions -->
<sec:http auto-config="true" use-expressions="false" >
<sec:intercept-url pattern="/admin/**" access="ROLE_ADMIN" />
<!-- access denied page -->
<sec:access-denied-handler error-page="/403" />
<sec:form-login
login-page="/login"
default-target-url="/admin/"
always-use-default-target="true"
login-processing-url="/j_spring_security_check"
authentication-failure-url="/login?error"
username-parameter="username"
password-parameter="password" />
<sec:logout logout-success-url="/login?logout" logout-url="/j_spring_security_logout" />
<!-- enable csrf protection -->
<sec:csrf disabled="true"/>
</sec:http>
<!--
<sec:authentication-manager alias="authenticationManager">
<sec:authentication-provider user-service-ref="myUserDetailsService" >
<sec:password-encoder hash="bcrypt" />
</sec:authentication-provider>
</sec:authentication-manager>
-->
</beans>