2016-04-17 27 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以更好地理解它。