2016-04-17 26 views
0

我使用Spring Boot(版本:1.3.2)以及spring web和security。Spring Security:SecurityContextHolder在生产中没有填充正确的用户数据

场景:我有一个外部认证服务,它向尝试访问我的spring应用程序的API的客户端发出OAuth2令牌。为了截取和理解令牌,我遵循了this教程中提到的配置。这是一个基于Spring的无状态REST Api JWT令牌基于身份验证。

问题:当我在本地主机上运行我的应用并尝试从不同浏览器(隐身模式)访问应用时,事情正在为我工​​作。当我将它部署到我的Ubuntu 12.04服务器时出现问题。每当我尝试访问标记为@PreAuthorize(“hasAnyRole('ADMIN')”)的方法时,虽然用户已登录并被授权使用该API,但我正在获取401。

工作情况记录从本地主机

2016-04-17 10:13:55 - Bound request context to thread: [email protected] 
2016-04-17 10:13:55 - Trying to match using Ant [pattern='/css/**'] 
2016-04-17 10:13:55 - Checking match of request : '/api/purchaseorders/get'; against '/css/**' 
2016-04-17 10:13:55 - Trying to match using Ant [pattern='/js/**'] 
2016-04-17 10:13:55 - Checking match of request : '/api/purchaseorders/get'; against '/js/**' 
2016-04-17 10:13:55 - Trying to match using Ant [pattern='/images/**'] 
2016-04-17 10:13:55 - Checking match of request : '/api/purchaseorders/get'; against '/images/**' 
2016-04-17 10:13:55 - Trying to match using Ant [pattern='/**/favicon.ico'] 
2016-04-17 10:13:55 - Checking match of request : '/api/purchaseorders/get'; against '/**/favicon.ico' 
2016-04-17 10:13:55 - Trying to match using Ant [pattern='/error'] 
2016-04-17 10:13:55 - Checking match of request : '/api/purchaseorders/get'; against '/error' 
2016-04-17 10:13:55 - No matches found 
2016-04-17 10:13:55 - /api/purchaseOrders/get at position 1 of 7 in additional filter chain; firing Filter: 'HeaderWriterFilter' 
2016-04-17 10:13:55 - Not injecting HSTS header since it did not match the requestMatcher org.springframework.se[email protected]54d08125 
2016-04-17 10:13:55 - /api/purchaseOrders/get at position 2 of 7 in additional filter chain; firing Filter: 'StatelessAuthenticationFilter' 
2016-04-17 10:13:55 - /api/purchaseOrders/get at position 3 of 7 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter' 
2016-04-17 10:13:55 - /api/purchaseOrders/get at position 4 of 7 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter' 
2016-04-17 10:13:55 - SecurityContextHolder not populated with anonymous token, as it already contained: '[email protected]' 
2016-04-17 10:13:55 - /api/purchaseOrders/get at position 5 of 7 in additional filter chain; firing Filter: 'SessionManagementFilter' 
2016-04-17 10:13:55 - Delegating to org.springframework.security.w[email protected]1d3565e1 
2016-04-17 10:13:55 - /api/purchaseOrders/get at position 6 of 7 in additional filter chain; firing Filter: 'ExceptionTranslationFilter' 
2016-04-17 10:13:55 - /api/purchaseOrders/get at position 7 of 7 in additional filter chain; firing Filter: 'FilterSecurityInterceptor' 
2016-04-17 10:13:55 - Checking match of request : '/api/purchaseorders/get'; against '/' 
2016-04-17 10:13:55 - Checking match of request : '/api/purchaseorders/get'; against '/resources/**' 
2016-04-17 10:13:55 - Checking match of request : '/api/purchaseorders/get'; against '/app/login/**' 
2016-04-17 10:13:55 - Checking match of request : '/api/purchaseorders/get'; against '/api/**' 
2016-04-17 10:13:55 - Secure object: FilterInvocation: URL: /api/purchaseOrders/get; Attributes: [fullyAuthenticated] 
2016-04-17 10:13:55 - Previously Authenticated: [email protected] 
2016-04-17 10:13:55 - Voter: org.sp[email protected]446e8d44, returned: 1 
2016-04-17 10:13:55 - Authorization successful 
2016-04-17 10:13:55 - RunAsManager did not change Authentication object 
2016-04-17 10:13:55 - /api/purchaseOrders/get reached end of additional filter chain; proceeding with original chain 
2016-04-17 10:13:55 - DispatcherServlet with name 'dispatcherServlet' processing GET request for [/api/purchaseOrders/get] 
2016-04-17 10:13:55 - Looking up handler method for path /api/purchaseOrders/get 
2016-04-17 10:13:55 - Did not find handler method for [/api/purchaseOrders/get] 
2016-04-17 10:13:55 - Looking up handler method for path /api/purchaseOrders/get 
2016-04-17 10:13:55 - Returning handler method [public org.springframework.http.ResponseEntity<java.util.List<com.mycompany.inventory.dto.PurchaseOrderDTO>> com.mycompany.inventory.rest.controllers.PurchaseOrderApiController.getAllPurchaseOrders()] 
2016-04-17 10:13:55 - Returning cached instance of singleton bean 'purchaseOrderApiController' 
2016-04-17 10:13:55 - Last-Modified value for [/api/purchaseOrders/get] is: -1 
2016-04-17 10:13:55 - Opening JPA EntityManager in OpenEntityManagerInViewInterceptor 
2016-04-17 10:13:55 - Secure object: ReflectiveMethodInvocation: public org.springframework.http.ResponseEntity com.mycompany.inventory.rest.controllers.PurchaseOrderApiController.getAllPurchaseOrders(); target is of class [com.mycompany.inventory.rest.controllers.PurchaseOrderApiController]; Attributes: [[authorize: 'hasAnyRole('ADMIN')', filter: 'null', filterTarget: 'null']] 
2016-04-17 10:13:55 - Previously Authenticated: [email protected] 
2016-04-17 10:13:55 - Voter: org.springframewor[email protected]6bb04370, returned: 1 
2016-04-17 10:13:55 - Authorization successful 
2016-04-17 10:13:55 - RunAsManager did not change Authentication object 
2016-04-17 10:13:55 - Found thread-bound EntityManager [[email protected]] for JPA transaction 
2016-04-17 10:13:55 - Creating new transaction with name [com.mycompany.inventory.servicesImpl.PurchaseOrderServiceImpl.getPurchaseOrders]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT 
2016-04-17 10:13:55 - Exposing JPA transaction as JDBC transaction [org.springframewo[email protected]3400e582] 
2016-04-17 10:13:55 - Found thread-bound EntityManager [[email protected]] for JPA transaction 
2016-04-17 10:13:55 - Participating in existing transaction 
2016-04-17 10:13:55 - Found thread-bound EntityManager [[email protected]] for JPA transaction 
2016-04-17 10:13:55 - Participating in existing transaction 
2016-04-17 10:13:55 - Initiating transaction commit 
2016-04-17 10:13:55 - Committing JPA transaction on EntityManager [[email protected]] 
2016-04-17 10:13:55 - Not closing pre-bound JPA EntityManager after transaction 
2016-04-17 10:13:55 - Written [[]] as "application/json;charset=UTF-8" using [org.springfr[email protected]76cde05c] 
2016-04-17 10:13:55 - Null ModelAndView returned to DispatcherServlet with name 'dispatcherServlet': assuming HandlerAdapter completed request handling 
2016-04-17 10:13:55 - Closing JPA EntityManager in OpenEntityManagerInViewInterceptor 
2016-04-17 10:13:55 - Closing JPA EntityManager 
2016-04-17 10:13:55 - Successfully completed request 
2016-04-17 10:13:55 - Chain processed normally 
2016-04-17 10:13:55 - Cleared thread-bound request context: [email protected] 

正如你可以看到: SecurityContextHolder中不填充匿名的原因,因为它已经包含:'[email protected] '

工作案例中的安全上下文报告已存在用户认证。即使这有效,我想知道这是否是正确的行为?由于我的配置是针对无状态会话的,因此安全上下文为什么要在其上下文中查找现有的身份验证条目?这是预期的吗?

不能工作的情况,从登录服务器

2016-04-17 04:40:19 - Bound request context to thread: [email protected] 
2016-04-17 04:40:19 - Trying to match using Ant [pattern='/css/**'] 
2016-04-17 04:40:19 - Checking match of request : '/api/purchaseorders/get'; against '/css/**' 
2016-04-17 04:40:19 - Trying to match using Ant [pattern='/js/**'] 
2016-04-17 04:40:19 - Checking match of request : '/api/purchaseorders/get'; against '/js/**' 
2016-04-17 04:40:19 - Trying to match using Ant [pattern='/images/**'] 
2016-04-17 04:40:19 - Checking match of request : '/api/purchaseorders/get'; against '/images/**' 
2016-04-17 04:40:19 - Trying to match using Ant [pattern='/**/favicon.ico'] 
2016-04-17 04:40:19 - Checking match of request : '/api/purchaseorders/get'; against '/**/favicon.ico' 
2016-04-17 04:40:19 - Trying to match using Ant [pattern='/error'] 
2016-04-17 04:40:19 - Checking match of request : '/api/purchaseorders/get'; against '/error' 
2016-04-17 04:40:19 - No matches found 
2016-04-17 04:40:19 - /api/purchaseOrders/get at position 1 of 7 in additional filter chain; firing Filter: 'HeaderWriterFilter' 
2016-04-17 04:40:19 - Not injecting HSTS header since it did not match the requestMatcher org.springframework.se[email protected]4a77b460 
2016-04-17 04:40:19 - /api/purchaseOrders/get at position 2 of 7 in additional filter chain; firing Filter: 'StatelessAuthenticationFilter' 
2016-04-17 04:40:19 - /api/purchaseOrders/get at position 3 of 7 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter' 
2016-04-17 04:40:19 - /api/purchaseOrders/get at position 4 of 7 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter' 
2016-04-17 04:40:19 - Populated SecurityContextHolder with anonymous token: 'org.sprin[email protected]905571d8: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.sprin[email protected]0: RemoteIpAddress: 122.171.94.145; SessionId: 4094950BB43FBE280B81842F649BA18E; Granted Authorities: ROLE_ANONYMOUS' 
2016-04-17 04:40:19 - /api/purchaseOrders/get at position 5 of 7 in additional filter chain; firing Filter: 'SessionManagementFilter' 
2016-04-17 04:40:19 - /api/purchaseOrders/get at position 6 of 7 in additional filter chain; firing Filter: 'ExceptionTranslationFilter' 
2016-04-17 04:40:19 - /api/purchaseOrders/get at position 7 of 7 in additional filter chain; firing Filter: 'FilterSecurityInterceptor' 
2016-04-17 04:40:19 - Checking match of request : '/api/purchaseorders/get'; against '/' 
2016-04-17 04:40:19 - Checking match of request : '/api/purchaseorders/get'; against '/resources/**' 
2016-04-17 04:40:19 - Checking match of request : '/api/purchaseorders/get'; against '/app/login/**' 
2016-04-17 04:40:19 - Checking match of request : '/api/purchaseorders/get'; against '/api/**' 
2016-04-17 04:40:19 - Secure object: FilterInvocation: URL: /api/purchaseOrders/get; Attributes: [fullyAuthenticated] 
2016-04-17 04:40:19 - Previously Authenticated: org.sprin[email protected]905571d8: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.sprin[email protected]0: RemoteIpAddress: 122.171.94.145; SessionId: 4094950BB43FBE280B81842F649BA18E; Granted Authorities: ROLE_ANONYMOUS 
2016-04-17 04:40:19 - Voter: org.sp[email protected]385462f, returned: -1 
2016-04-17 04:40:19 - AuditEvent [timestamp=Sun Apr 17 04:40:19 UTC 2016, principal=anonymousUser, type=AUTHORIZATION_FAILURE, data={type=org.springframework.security.access.AccessDeniedException, message=Access is denied}] 
2016-04-17 04:40:19 - Access is denied (user is anonymous); redirecting to authentication entry point 
org.springframework.security.access.AccessDeniedException: Access is denied 
at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:83) ~[spring-security-core-4.0.3.RELEASE.jar!/:4.0.3.RELEASE] 
     at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:232) ~[spring-security-core-4.0.3.RELEASE.jar!/:4.0.3.RELEASE] 
     at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:123) ~[spring-security-web-4.0.3.RELEASE.jar!/:4.0.3.RELEASE] 
     at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:90) ~[spring-security-web-4.0.3.RELEASE.jar!/:4.0.3.RELEASE] 
     at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) [spring-security-web-4.0.3.RELEASE.jar!/:4.0.3.RELEASE] 
     at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:114) ~[spring-security-web-4.0.3.RELEASE.jar!/:4.0.3.RELEASE] 
     at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) [spring-security-web-4.0.3.RELEASE.jar!/:4.0.3.RELEASE] 
     at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:122) [spring-security-web-4.0.3.RELEASE.jar!/:4.0.3.RELEASE] 
     at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) [spring-security-web-4.0.3.RELEASE.jar!/:4.0.3.RELEASE] 
     at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111) [spring-security-web-4.0.3.RELEASE.jar!/:4.0.3.RELEASE] 
     at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) [spring-security-web-4.0.3.RELEASE.jar!/:4.0.3.RELEASE] 
     at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:169) [spring-security-web-4.0.3.RELEASE.jar!/:4.0.3.RELEASE] 
     at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) [spring-security-web-4.0.3.RELEASE.jar!/:4.0.3.RELEASE] 
     at com.drivojoy.inventory.helpers.StatelessAuthenticationFilter.doFilter(StatelessAuthenticationFilter.java:30) [classes!/:na] 
     at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) [spring-security-web-4.0.3.RELEASE.jar!/:4.0.3.RELEASE] 
     at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64) [spring-security-web-4.0.3.RELEASE.jar!/:4.0.3.RELEASE] 
     at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.2.4.RELEASE.jar!/:4.2.4.RELEASE] 
     at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) [spring-security-web-4.0.3.RELEASE.jar!/:4.0.3.RELEASE] 
     at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213) [spring-security-web-4.0.3.RELEASE.jar!/:4.0.3.RELEASE] 
     at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:176) [spring-security-web-4.0.3.RELEASE.jar!/:4.0.3.RELEASE] 
     at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346) [spring-web-4.2.4.RELEASE.jar!/:4.2.4.RELEASE] 
     at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262) [spring-web-4.2.4.RELEASE.jar!/:4.2.4.RELEASE] 
     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) [tomcat-embed-core-8.0.30.jar!/:8.0.30] 
     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) [tomcat-embed-core-8.0.30.jar!/:8.0.30] 
     at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) [spring-web-4.2.4.RELEASE.jar!/:4.2.4.RELEASE] 
     at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.2.4.RELEASE.jar!/:4.2.4.RELEASE] 
     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) [tomcat-embed-core-8.0.30.jar!/:8.0.30] 
     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) [tomcat-embed-core-8.0.30.jar!/:8.0.30] 
     at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:87) [spring-web-4.2.4.RELEASE.jar!/:4.2.4.RELEASE] 

正如你所看到的:匿名令牌人口较少SecurityContextHolder的:“org.sprin[email protected]905571d8:负责人:anonymousUser;证书:[PROTECTED];已验证:true;详细信息:org.sprin[email protected]0:RemoteIpAddress:122.171.94.145; SessionId:4094950BB43FBE280B81842F649BA18E;授予的权限:ROLE_ANONYMOUS”

弹簧安全上下文加载在它的上下文匿名用户。以下是我的过滤器。

public class StatelessAuthenticationFilter extends GenericFilterBean { 

     private final TokenAuthenticationService authenticationService; 

     public StatelessAuthenticationFilter(TokenAuthenticationService authenticationService) { 
      this.authenticationService = authenticationService; 
     } 

     @Override 
     public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) 
       throws IOException, ServletException { 
      HttpServletRequest httpRequest = (HttpServletRequest) request; 
      Authentication authentication = authenticationService.getAuthentication(httpRequest); 
      SecurityContextHolder.getContext().setAuthentication(authentication); 
      filterChain.doFilter(request, response); 
      SecurityContextHolder.getContext().setAuthentication(null); 
     } 
    } 

我已经调试直到这点,并发现,在所有的情况下,我的安全上下文设置与正确的身份验证和授权的用户。

任何人都可以帮我理解问题的根源吗?

在此先感谢。

回答

0

我找到了根本原因球员。事实证明,JWT令牌解析器抛出了一个异常: “XXX之前不能接受JWT当前时间:XXX”

我的Ubuntu服务器上的时间比发出令牌的服务器滞后1分钟,由于这个原因,令牌验证失败。

请参考this code以更好地理解它。