2016-05-30 13 views
22

A 500 điểm bounty được cung cấp. Complete code và hướng dẫn để nhanh chóng tái tạo vấn đề được đưa ra dưới đây.
HttpSession null sau khi thay thế AuthorizationRequest


CÁC VẤN ĐỀ:
Các HttpSession trở thành null sau một thực hiện tùy chỉnh của DefaultOAuth2RequestFactory thay thế hiện tại với một AuthorizationRequest lưu AuthorizationRequest. này gây thất bại của yêu cầu tiếp theo để /oauth/tokenCsrfFilter trong chuỗi lọc Xuân An trước /oauth/token endpoint là không thể tìm thấy một session Csrf token trong null session để so sánh với 's Csrf token request.


KIỂM SOÁT LƯU TRONG LỖI:

Biểu đồ dưới đây minh họa nơi Bước 14Bước 15 bằng cách nào đó null -ify các HttpSession. (Hoặc có thể không khớp với số JSESSIONID.) A SYSO khi bắt đầu CustomOAuth2RequestFactory.java trong Bước 14 cho thấy thực tế có một số HttpSession thực tế chứa đúng CsrfToken. Tuy nhiên, bằng cách nào đó, HttpSession đã trở thành null vào thời điểm Bước 15 kích hoạt cuộc gọi từ máy khách tại địa chỉ localhost:8080/login trở lại điểm cuối localhost:9999/oauth/token.

Điểm ngắt được thêm vào mỗi dòng của HttpSessionSecurityContextRepository được đề cập trong nhật ký gỡ lỗi bên dưới. (Nó nằm trong thư mục Maven Dependencies của dự án authserver eclipse.) Các điểm ngắt này xác nhận rằng HttpSessionnull khi yêu cầu cuối cùng đến /oauth/token được thực hiện trong sơ đồ dưới đây. (Dưới cùng bên trái của sơ đồ.)nullHttpSession có thể là do JSESSIONID vẫn còn trong trình duyệt bị lỗi thời sau khi mã tùy chỉnh DefaultOAuth2RequestFactory chạy.

Làm cách nào để khắc phục sự cố này, sao cho cùng HttpSession vẫn còn trong cuộc gọi cuối cùng đến điểm cuối /oauth/token, sau khi kết thúc Bước 15 trong sơ đồ?


MÃ LIÊN QUAN VÀ GỖ:

Mã hoàn toàn CustomOAuth2RequestFactory.javacan be viewed at a file sharing site by clicking on this link.Chúng ta có thể đoán rằng nullsession là do một trong hai 1.) các JSESSIONID không được cập nhật trong trình duyệt theo mã trong số CustomOAuth2RequestFactory hoặc 2.) HttpSession thực sự là null đã được hợp nhất.

Các mùa xuân Boot bản ghi gỡ lỗi cho các cuộc gọi đến /oauth/token sau Bước 15 nêu rõ rằng không có HttpSession bởi thời điểm đó, và có thể được đọc như sau:

2016-05-30 15:33:42.630 DEBUG 13897 --- [io-9999-exec-10] o.s.security.web.FilterChainProxy  : /oauth/token at position 1 of 12 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter' 
2016-05-30 15:33:42.631 DEBUG 13897 --- [io-9999-exec-10] o.s.security.web.FilterChainProxy  : /oauth/token at position 2 of 12 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter' 
2016-05-30 15:33:42.631 DEBUG 13897 --- [io-9999-exec-10] w.c.HttpSessionSecurityContextRepository : No HttpSession currently exists 
2016-05-30 15:33:42.631 DEBUG 13897 --- [io-9999-exec-10] w.c.HttpSessionSecurityContextRepository : No SecurityContext was available from the HttpSession: null. A new one will be created. 
2016-05-30 15:33:42.631 DEBUG 13897 --- [io-9999-exec-10] o.s.security.web.FilterChainProxy  : /oauth/token at position 3 of 12 in additional filter chain; firing Filter: 'HeaderWriterFilter' 
2016-05-30 15:33:42.631 DEBUG 13897 --- [io-9999-exec-10] o.s.s.w.header.writers.HstsHeaderWriter : Not injecting HSTS header since it did not match the requestMatcher org.springframework.se[email protected]2fe29f4b 
2016-05-30 15:33:42.631 DEBUG 13897 --- [io-9999-exec-10] o.s.security.web.FilterChainProxy  : /oauth/token at position 4 of 12 in additional filter chain; firing Filter: 'CsrfFilter' 
2016-05-30 15:33:42.644 DEBUG 13897 --- [io-9999-exec-10] o.s.security.web.csrf.CsrfFilter   : Invalid CSRF token found for http://localhost:9999/uaa/oauth/token 
2016-05-30 15:33:42.644 DEBUG 13897 --- [io-9999-exec-10] w.c.HttpSessionSecurityContextRepository : SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession. 
2016-05-30 15:33:42.644 DEBUG 13897 --- [io-9999-exec-10] s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed 


TÁI TẠO VẤN ĐỀ VỀ MÁY TÍNH CỦA BẠN:

Bạn có thể tạo lại sự cố trên bất kỳ máy tính nào chỉ trong vài phút bằng cách làm theo các bước đơn giản này ps:

1.) Tải xuống zipped version of the app from a file sharing site by clicking on this link.

2.) Giải nén ứng dụng bằng cách gõ: tar -zxvf oauth2.tar(4).gz

3.) Khởi chạy ứng dụng authserver bằng cách điều hướng đến oauth2/authserver và sau đó gõ mvn spring-boot:run.

4.) Khởi chạy ứng dụng resource bằng cách điều hướng đến oauth2/resource và sau đó gõ mvn spring-boot:run

5.) Khởi chạy ứng dụng ui bằng cách điều hướng đến oauth2/ui và sau đó gõ mvn spring-boot:run

6.) Mở trình duyệt web và điều hướng đến http : // localhost : 8080

7.) Nhấp Login và sau đó nhập Frodo làm người dùng và MyRing làm mật khẩu và nhấp vào để nộp.

8.) Nhập 5309 làm Pin Code và nhấp gửi. Điều này sẽ kích hoạt lỗi được hiển thị ở trên.

Các mùa xuân Boot bản ghi gỡ lỗi sẽ hiển thị A LOT của SYSO, mang đến cho các giá trị của các biến như XSRF-TOKENHttpSession tại mỗi bước thể hiện trong sơ đồ. SYSO giúp phân đoạn nhật ký gỡ lỗi để chúng dễ hiểu hơn. Và tất cả các SYSO được thực hiện bởi một lớp được gọi bởi các lớp khác, vì vậy bạn có thể thao tác với lớp học SYSO để thay đổi báo cáo ở mọi nơi trong luồng điều khiển. Tên của lớp học SYSO -generating là TestHTTP và mã nguồn của nó có thể được tìm thấy trong cùng một gói demo.


SỬ DỤNG Debugger:

1.) Chọn cửa sổ terminal đang chạy ứng dụng authserver và gõ Ctrl-C để ngăn chặn các ứng dụng authserver.

2.) Nhập ba ứng dụng (authserver, resourceui) vào nhật thực như dự án maven hiện.

3.Trong Trình thám hiểm dự án nhật thực của authserver, nhấp để mở rộng thư mục Maven Dependencies, sau đó cuộn xuống bên trong nó để nhấp vào để mở rộng Spring-Security-web... jar như được minh họa bằng màu cam trong hình ảnh bên dưới. Sau đó cuộn để tìm và mở rộng gói org.springframework.security.web.context. Sau đó, nhấp đúp để mở lớp HttpSessionSecurityContextRepository được đánh dấu bằng màu xanh lam trong ảnh chụp màn hình bên dưới. Thêm điểm ngắt cho mỗi dòng trong lớp này. Bạn có thể muốn thực hiện tương tự với lớp SecurityContextPersistenceFilter trong cùng một gói. Các điểm ngắt này sẽ cho phép bạn xem giá trị của HttpSession, hiện đang trở thành null trước khi kết thúc luồng kiểm soát, nhưng cần phải có giá trị hợp lệ có thể được ánh xạ tới XSRF-TOKEN để giải quyết OP này.

4.) Trong gói demo của ứng dụng, thêm breakpoint trong CustomOAuth2RequestFactory.java. Sau đó, Debug As... Spring Boot App để bắt đầu trình gỡ lỗi.

5.) Sau đó lặp lại các bước từ 6 đến 8 ở trên. Bạn có thể xóa bộ nhớ cache của trình duyệt trước mỗi lần thử mới. Và bạn có thể muốn tab Mạng của các công cụ phát triển của trình duyệt mở.

Trả lời

1

Bạn đã khắc phục được sự cố chưa? Tôi đã nhìn xung quanh để tìm một mẫu đầy đủ của 2FA cùng với spring-security-oauth2. Thật tuyệt vời khi bạn đã đăng các khái niệm đầy đủ của mình và các nguồn hoàn chỉnh.

tôi đã cố gắng gói của bạn và vấn đề của bạn chỉ có thể được giải quyết bằng cách thay đổi chỉ 1 dòng mã trong AuthserverApplication.java bạn

@Override 
    protected void configure(HttpSecurity http) throws Exception { 
     // @formatter:off 
     http 
      .formLogin().loginPage("/login").permitAll() 
     .and() 
       .requestMatchers().antMatchers("/login", "/oauth/authorize", "/secure/two_factor_authentication", "/pincode") 
     .and() 
       .authorizeRequests().anyRequest().authenticated(); 
     // @formatter:on 
    } 

cấu hình ban đầu của bạn bằng cách thông qua các chuỗi xác thực về an ninh mùa xuân mà trở bạn một null đối tượng xác thực.

Tôi cũng muốn khuyên bạn thay đổi tạo Bean của CustomOAuth2RequestFactory để sau đó ghi đè lên tất cả các OAuth2RequestFactory trong chuỗi

@Bean 
    public OAuth2RequestFactory customOAuth2RequestFactory(){ 
     return new CustomOAuth2RequestFactory(clientDetailsService); 
    } 

Đối với mã bạn đã thêm để xử lý các CSRF, bạn có thể chỉ đơn giản là loại bỏ ví dụ: bộ điều khiển 2FA:

@Controller 
@RequestMapping(TwoFactorAuthenticationController.PATH) 
public class TwoFactorAuthenticationController { 
    private static final Logger LOG = LoggerFactory.getLogger(TwoFactorAuthenticationController.class); 
    public static final String PATH = "/secure/two_factor_authentication"; 
    public static final String AUTHORIZE_PATH = "/oauth/authorize"; 
    public static final String ROLE_TWO_FACTOR_AUTHENTICATED = "ROLE_TWO_FACTOR_AUTHENTICATED"; 

    private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy(); 

    @RequestMapping(method = RequestMethod.GET) 
    public String auth(HttpServletRequest request, HttpSession session, HttpServletResponse resp/*, ....*/) { 
     System.out.println("-------- inside GET /secure/two_factor_authentication --------------"); 
     if (AuthenticationUtil.isAuthenticatedWithAuthority(ROLE_TWO_FACTOR_AUTHENTICATED)) { 
      LOG.info("User {} already has {} authority - no need to enter code again", ROLE_TWO_FACTOR_AUTHENTICATED); 
//   throw ....; 
     } 
     else if (session.getAttribute(CustomOAuth2RequestFactory.SAVED_AUTHORIZATION_REQUEST_SESSION_ATTRIBUTE_NAME) == null) { 
//   LOG.warn("Error while entering 2FA code - attribute {} not found in session.", CustomOAuth2RequestFactory.SAVED_AUTHORIZATION_REQUEST_SESSION_ATTRIBUTE_NAME); 
//   throw ....; 
     } 
     return "pinCode"; 
    } 

    @RequestMapping(method = RequestMethod.POST) 
    public String auth(FormData formData, HttpServletRequest req, HttpServletResponse resp, 
              SessionStatus sessionStatus, Principal principal, Model model) 
     throws IOException{ 

     if (formData.getPinVal()!=null) { 
      if(formData.getPinVal().equals("5309")){ 
       AuthenticationUtil.addAuthority(ROLE_TWO_FACTOR_AUTHENTICATED); 
       return "redirect:"+AUTHORIZE_PATH; 
      }; 
     }; 

     return "pinCode"; 
    } 
} 

Vui lòng cho tôi biết nếu bạn muốn có mã nguồn hoàn chỉnh sau khi dọn dẹp.

+0

Cảm ơn bạn RẤT NHIỀU. Bạn đã giải quyết được vấn đề. Tôi đánh dấu đây là câu trả lời được chấp nhận. Tôi ước rằng thời gian của chúng tôi đã cho phép tiền thưởng vẫn có sẵn khi bạn đưa ra câu trả lời của bạn, bởi vì câu trả lời của bạn là giải pháp thực sự cho vấn đề. Chào mừng bạn đến tràn ngăn xếp. – CodeMed

+0

Đây là một chiến thắng-thắng vì tôi cần một mẫu hoàn chỉnh và biểu đồ khái niệm rõ ràng cho nhóm của tôi để làm việc với. Cảm ơn bạn rất nhiều vì sự đóng góp của bạn đã giúp tôi tiết kiệm thời gian tạo ra của riêng mình. Dự án của bạn là nguồn hoàn chỉnh duy nhất tôi có thể tìm thấy trong cộng đồng. –

+0

Thay đổi nhỏ này cũng có thể khắc phục sự cố trong câu hỏi khác của bạn. http://stackoverflow.com/questions/37061697/invalid-xsrf-token-at-oauth-token –

3

Phiên này không phải là số trong ứng dụng authserver tại thời điểm cuộc gọi cuối cùng đến localhost :9999/uaa/oauth/token. Không chỉ có phiên, mà là JSESSIONID và mã thông báo csrf của giá trị đối sánh phiên hợp lệ có trong dòng kiểm soát giữa điểm mà người dùng gửi pin chính xác và điểm mà yêu cầu không thành công đến /oauth/token.

Vấn đề là có hai giá trị JSESSIONID và sai của hai giá trị được chọn để nhập cuộc gọi đến /oauth/token. Do đó, giải pháp nên đến từ việc sửa đổi các bộ lọc để xóa số JSESSIONID xấu sao cho có thể gửi giá trị chính xác.

Sau đây sẽ tóm tắt:


HttpSessionListener xác định được giá trị JSESSIONID

Để cô lập các vấn đề, tôi đã tạo ra một thực hiện HttpSessionListener và sau đó gọi nó từ một thực hiện tùy chỉnh của HttpLListener, như sau :

public class HttpSessionCollector implements HttpSessionListener, ServletContextListener { 

    private static final Set<HttpSession> sessions = ConcurrentHashMap.newKeySet(); 

    public void sessionCreated(HttpSessionEvent event) { 
     sessions.add(event.getSession()); 
    } 

    public void sessionDestroyed(HttpSessionEvent event) { 
     sessions.remove(event.getSession()); 
    } 

    public static Set<HttpSession> getSessions() { 
     return sessions; 
    } 

    public void contextCreated(ServletContextEvent event) { 
     event.getServletContext().setAttribute("HttpSessionCollector.instance", this); 
    } 

    public static HttpSessionCollector getCurrentInstance(ServletContext context) { 
     return (HttpSessionCollector) context.getAttribute("HttpSessionCollector.instance"); 
    } 

    @Override 
    public void contextDestroyed(ServletContextEvent arg0) { 
    } 

    @Override 
    public void contextInitialized(ServletContextEvent arg0) { 
    } 

} 

Tôi sau đó được gọi là ở trên HttpSessionListener trong việc thực hiện tùy chỉnh của OncePerRequestFilter, mà tôi đưa vào Xuân An Lọc Chain authserver ứng dụng của bạn để cung cấp thông tin chẩn đoán, như sau:

@Component 
public class DiagnoseSessionFilter extends OncePerRequestFilter implements ServletContextAware { 

    @Override 
    protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain fc) throws ServletException, IOException { 

    System.out.println("...........///////////// START OF DiagnoseSessionFilter.doFilterInternal() ///////////..........."); 
    //start of request stuff 
    System.out.println("\\\\\\\\\\ REQUEST ATTRIBUTES ARE: "); 
    if(req.getAttribute("_csrf")!=null){ 
     System.out.println("_csrf is: " + req.getAttribute("_csrf").toString()); 
    } 
    if(req.getAttribute("org.springframework.security.web.csrf.CsrfToken")!=null){ 
     CsrfToken ucsrf = (CsrfToken) req.getAttribute("org.springframework.security.web.csrf.CsrfToken"); 
     System.out.println("ucsrf.getToken() is: " + ucsrf.getToken()); 
    } 
    String reqXSRF = req.getHeader("XSRF-TOKEN"); 
    System.out.println("request XSRF-TOKEN header is: " + reqXSRF); 
    String reqCookie = req.getHeader("Cookie"); 
    System.out.println("request Cookie header is: " + reqCookie); 
    String reqSetCookie = req.getHeader("Set-Cookie"); 
    System.out.println("request Set-Cookie header is: " + reqSetCookie); 
    String reqReferrer = req.getHeader("referrer"); 
    System.out.println("request referrer header is: " + reqReferrer); 
    HttpSession rsess = req.getSession(false); 
    System.out.println("request.getSession(false) is: " + rsess); 
    if(rsess!=null){ 
     String sessid = rsess.getId(); 
     System.out.println("session.getId() is: "+sessid); 
    } 
    System.out.println("/////////// END OF REQUEST ATTRIBUTES "); 

    //end of request stuff 
    ServletContext servletContext = req.getServletContext(); 
    System.out.println("\\\\\\\\\\ START OF SESSION COLLECTOR STUFF "); 

    HttpSessionCollector collector = HttpSessionCollector.getCurrentInstance(servletContext); 
    Set<HttpSession> sessions = collector.getSessions(); 

    System.out.println("sessions.size() is: " + sessions.size()); 
    for(HttpSession sess : sessions){ 
     System.out.println("sess is: " + sess); 
     System.out.println("sess.getId() is: " + sess.getId()); 
     CsrfToken sessCsrf = (CsrfToken) sess.getAttribute("org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository.CSRF_TOKEN"); 
     System.out.println("csrf is: " + sessCsrf); 
     if(sessCsrf!=null){ 
      if(sessCsrf.getToken()!=null){ 
       System.out.println("sessCsrf.getToken() is: " + sessCsrf.getToken()); 
      } else { System.out.println("sessCsrf.getToken() is: null "); } 
     } else { System.out.println("sessCsrf is: null "); } 

     System.out.println("sess.getAttribute(SPRING_SECURITY_SAVED_REQUEST) is: " + sess.getAttribute("SPRING_SECURITY_SAVED_REQUEST")); 
     if(sess.getAttribute("SPRING_SECURITY_SAVED_REQUEST") instanceof DefaultSavedRequest){ 
      System.out.println("_____ START PRINTING SAVED REQUEST"); 
      DefaultSavedRequest savedReq = (DefaultSavedRequest) sess.getAttribute("SPRING_SECURITY_SAVED_REQUEST"); 
      List<Cookie> savedCookies = savedReq.getCookies(); 
      for(Cookie cook : savedCookies){ 
       String name = cook.getName();String value = cook.getValue(); 
       System.out.println("cookie name, value are: " + name + " , " + value); 
      } 
      Collection<String> savedHeaderNames = savedReq.getHeaderNames(); 
      for(String headerName : savedHeaderNames){ 
       System.out.println("headerName is: " + headerName); 
      } 
      List<Locale> savedLocales = savedReq.getLocales(); 
      for(Locale loc : savedLocales){ 
       System.out.println("loc.getLanguage() is: " + loc.getLanguage()); 
      } 
      String savedMethod = savedReq.getMethod(); 
      System.out.println("savedMethod is: " + savedMethod); 
      Map<String, String[]> savedParamMap = savedReq.getParameterMap(); 
      Iterator<Entry<String, String[]>> it = savedParamMap.entrySet().iterator(); 
      while (it.hasNext()) { 
       Entry<String, String[]> pair = it.next(); 
       System.out.println("savedParamMap: " + pair.getKey() + " = " + pair.getValue()); 
       it.remove(); // avoids a ConcurrentModificationException 
      } 
      Collection<String> savedParamNames = savedReq.getParameterNames(); 
      for(String savedParamName : savedParamNames){ 
       System.out.println("savedParamName: " + savedParamNames); 
      } 
      System.out.println("_____ DONE PRINTING SAVED REQUEST"); 

     } 

//  System.out.println("sess.getAttribute(SPRING_SECURITY_CONTEXT) is: " + sess.getAttribute("SPRING_SECURITY_CONTEXT")); 
     if(sess.getAttribute("SPRING_SECURITY_CONTEXT") instanceof SecurityContextImpl){ 
      SecurityContext ctxt = (SecurityContext) sess.getAttribute("SPRING_SECURITY_CONTEXT"); 
      Authentication auth = ctxt.getAuthentication(); 

      if(auth.getDetails() instanceof WebAuthenticationDetails){ 
       WebAuthenticationDetails dets = (WebAuthenticationDetails) auth.getDetails(); 
       System.out.println("dets.getSessionId() is: " + dets.getSessionId()); 
      } 
      System.out.println("auth.getAuthorities() is: " + auth.getAuthorities()); 
      System.out.println("auth.isAuthenticated() is: " + auth.isAuthenticated()); 
     } 
    } 

    SecurityContext context = SecurityContextHolder.getContext(); 
    System.out.println("...........///////////// END OF DiagnoseSessionFilter.doFilterInternal() ///////////..........."); 
    fc.doFilter(req, res); 

    } 
} 


Cô lập mã vấn đề:

kết hợp sau đây và tóm tắt dữ liệu chẩn đoán từ HttpSessionListener với các công cụ dành cho nhà phát triển trình duyệt web để biết các bước giữa người dùng nhấp vào gửi trên chế độ xem mã pin và trình duyệt trả về từ chối từ điểm cuối /oauth/token.

Như bạn có thể thấy, có hai giá trị JSESSIONID nổi xung quanh. Một trong các giá trị là chính xác, trong khi giá trị khác thì không. Giá trị không chính xác được chuyển vào yêu cầu đến /oauth/token và nguyên nhân bị từ chối, mặc dù thông số csrf đã qua là chính xác. Vì vậy, giải pháp cho vấn đề này có thể sẽ đến từ việc thay đổi các bước dưới đây để dừng lại đặt cái xấu JSESSIONID ở vị trí của tốt nhất:

1.) POST http://localhost:9999/uaa/secure/two_factor_authentication 
    request headers: 
     Referer: 9999/uaa/secure/two_factor_authentication 
     Cookie: 
      JSESSIONID: ....95CB77  
         ....918636 
      XSRF-TOKEN: ....862a73 
    filter chain: 
     DiagnoseSessionFilter: 
      request stuff: 
       Cookie header: 
        JSESSIONID: ....95CB77 
           ....918636 
        XSRF-TOKEN: ....862a73 
       request.getSession(false).getId(): ....95CB77 
      session collector stuff: 
       JSESSIONID: ....95CB77 
       csrf: ....862a73 
       SPRING_SECURITY_SAVED_REQUEST is null 
      user details (from Authentication object with user/request 
       JSESSIONID: ....ED927C 
       Authenticated = true, with roles 
     Complete the filter chain 
     DiagnoseSessionFilter (again) 
      request stuff: 
       csrf attribute: ....862a73 
       Cookie header: 
        JSESSIONID: ....95CB77 
           ....918636 
        XSRF-TOKEN: ....862a73 
       request.getSession(false).getId(): 95CB77 
      session collector stuff: 
       JSESSIONID: ....95CB77 
       csrf is: 862a73 
       SPRING_SECURITY_SAVED_REQUEST is null 
      user details (Authentication for user/session/request) 
       JSESSIONID: ....ED927C 
       Authenticated = true, with authorities 
     POST/secure/two_factor_authenticationControllerMethod 
      do some stuff 
    response: 
     Location: 9999/uaa/oauth/authorize?.... 
     XSRF-TOKEN: ....862a73 

2.) GET http://localhost:9999/uaa/oauth/authorize?... 
    request headers: 
     Host: localhost:9999 
     Referer: 9999/uaa/secure/two_factor_authentication 
     Cookie: 
      JSESSIONID: ....95CB77  
         ....918636 
      XSRF-TOKEN: ....862a73 
    FilterChain 
     DiagnoseSessionFilter 
      request stuff: 
       Cookie header is: JSESSIONID: ....95CB77 
               ....918636 
            XSRF-TOKEN: ....862a73 
       request.getSession(false).getId(): 95CB77 
      session collector stuff: 
       JSESSIONID: ....95CB77 
       csrf is: ....862a73 
       SPRING_SECURITY_SAVED_REQUEST is: null 
      user details (Authentication object with user/session/req) 
       JSESSIONID: ....ED927C 
       Authenticated = true with ALL roles. 
     rest of filter chain 
     TwoFactorAuthenticationFilter 
      request stuff: 
       csrf request attribute is: ....862a73 
       cookie header: 
        JSESSIONID: ....95CB77 
           ....918636 
        XSRF-TOKEN: ....862a73 
       request.getSession(false).getId() is: ....95CB77 
       updateCsrf is: ....862a73 
      response stuff: 
       XSRF-TOKEN header (after manual update): ....862a73 
     DiagnoseSessionFilter: 
      request stuff: 
       _csrf request attribute: ....862a73 
       Cookie header: 
        JSESSIONID: ....95CB77 
           ....918636 
        XSRF-TOKEN: ....862a73 
        request.getSession(false).getId() is: ....95CB77 
      session collector stuff: 
       JSESSIONID: ....95CB77 
       csrf is: ....862a73 
       SPRING_SECURITY_SAVED_REQUEST is: null 
      user details (Authentication for user/session/request) 
       JSESSIONID: ....ED927C 
       Authenticated is true, with ALL roles. 
     CustomOAuth2RequestFactory 
      request stuff: 
       _csrf request parameter is: ....862a73 
       Cookie header: 
        JSESSIONID: ....95CB77 
           ....918636 
        XSRF-TOKEN: ....862a73 
       request.getSession(false).getId() is: ....95CB77 
       updateCsrf: ....862a73 
      response stuff: 
       XSRF-TOKEN header: ....862a73 
      session attribute printout 
       csrf: ....862a73 
       SPRING_SECURITY_CONTEXT (not printed, so don't know values) 
    response: 
     Location: 8080/login?code=myNwd7&state=f6b3Km 
     XSRF-TOKEN: ....862a73 

3.) GET http://localhost:8080/login?code=myNwd7&state=f6b3Km 
    request headers: 
     Host: localhost:8080 
     Referer: 9999/uaa/secure/two_factor_authentication 
     Cookie: 
      JSESSIONID: ....918636 
      XSRF-TOKEN: ....862a73 
    UiAppFilterChain: 
     HttpSessionSecurityContextRepository 
      creates new SPRING_SECURITY_CONTEXT to replace null one 
     OAuth2ClientAuthenticationProcessingFilter (position 8 of 14) 
      AuthorizationCodeAccessTokenProvider 
       Retrieving token from 9999/uaa/oauth/token 
    AuthServerFilterChain: 
     DiagnoseSessionFilter 
      request stuff: 
       XSRF-TOKEN header is: null 
       Cookie header is: null 
       Set-Cookie header is: null 
       referrer header is: null 
       request.getSession(false) is: null 
      session collector stuff: 
       JSESSIONID: ....95CB77 
       sessCsrf.getToken() is: 862a73 
       SPRING_SECURITY_SAVED_REQUEST is: null 
       Authenticated is true but with ONLY these roles: 
        ROLE_HOBBIT, ROLE_TWO_FACTOR_AUTHENTICATION_ENABLED 
      SecurityContextPersistenceFilter 
       reports no HttpSession and no SPRING_SECURITY_CONTEXT 
      CsrfFilter 
       rejects request to /oauth/token due to no session % csrf 

    response headers: 
     Set-Cookie: 
      XSRF-TOKEN: ....527fbe 
      X-Frame-Options: DENY 

tôi sẽ cố gắng dành một ít thời gian hơn với điều này để tiếp tục cô lập giải pháp, với số điểm bạn đang cung cấp. Nhưng ở trên nên đáng kể thu hẹp vấn đề.

Tôi đăng bài này trước khi hoàn tất vì thời gian tiền thưởng của bạn sắp hết hạn.

Các vấn đề liên quan