8.1.4 Authentication in a Web Application

8.1.4 Authentication in a Web Application

Now let’s explore the situation where you are using Spring Security in a web application (without web.xml security enabled). How is a user authenticated and the security context established?web

如今讓咱們研究一下在web應用程序中使用Spring安全性的狀況(沒有web.xml安全啓用)。如何對用戶進行身份驗證並創建安全上下文?瀏覽器

Consider a typical web application’s authentication process:安全

考慮一個典型的web應用程序的身份驗證過程:服務器

  1. You visit the home page, and click on a link.
  2. A request goes to the server, and the server decides that you’ve asked for a protected resource.
  3. As you’re not presently authenticated, the server sends back a response indicating that you must authenticate. The response will either be an HTTP response code, or a redirect to a particular web page.
  4. Depending on the authentication mechanism, your browser will either redirect to the specific web page so that you can fill out the form, or the browser will somehow retrieve your identity (via a BASIC authentication dialogue box, a cookie, a X.509 certificate etc.).
  5. The browser will send back a response to the server. This will either be an HTTP POST containing the contents of the form that you filled out, or an HTTP header containing your authentication details.
  6. Next the server will decide whether or not the presented credentials are valid. If they’re valid, the next step will happen. If they’re invalid, usually your browser will be asked to try again (so you return to step two above).
  7. The original request that you made to cause the authentication process will be retried. Hopefully you’ve authenticated with sufficient granted authorities to access the protected resource. If you have sufficient access, the request will be successful. Otherwise, you’ll receive back an HTTP error code 403, which means "forbidden".
  1. 您能夠訪問主頁,並單擊連接。
  2. 一個請求到達服務器,服務器決定您請求的是受保護的資源。
  3. 因爲您目前沒有通過身份驗證,服務器將返回一個響應,指示您必須進行身份驗證。響應能夠是HTTP響應代碼,也能夠重定向到特定的web頁面。
  4. 根據身份驗證機制,瀏覽器將重定向到特定的web頁面,以便您能夠填寫表單,或者瀏覽器將以某種方式檢索您的身份(經過基自己份驗證對話框、cookie、X.509證書等)。
  5. 瀏覽器將向服務器發回響應。這將是一個HTTP POST,其中包含您填寫的表單的內容,或者是一個HTTP header,其中包含您的身份驗證詳細信息。
  6. 接下來,服務器將決定所提供的憑證是否有效。若是它們是有效的,下一步就會發生。若是它們無效,一般會要求您的瀏覽器重試一次(所以返回到上面的步驟2)。
  7. 將重試致使身份驗證過程的原始請求。但願您已經使用足夠的受權權限進行了身份驗證,以訪問受保護的資源。若是您有足夠的訪問權限,請求將會成功。不然,您將收到一個HTTP錯誤代碼403,這意味着「禁止」。

Spring Security has distinct classes responsible for most of the steps described above. The main participants (in the order that they are used) are the ExceptionTranslationFilter, an AuthenticationEntryPoint and an "authentication mechanism", which is responsible for calling the AuthenticationManager which we saw in the previous section.cookie

Spring Security有不一樣的類負責上面描述的大多數步驟。主要參與者(按使用順序)是ExceptionTranslationFilter、AuthenticationEntryPoint和「身份驗證機制」,該機制負責調用咱們在上一節中看到的authenticationmanager。session

ExceptionTranslationFilter

ExceptionTranslationFilter is a Spring Security filter that has responsibility for detecting any Spring Security exceptions that are thrown. Such exceptions will generally be thrown by an AbstractSecurityInterceptor, which is the main provider of authorization services. We will discuss AbstractSecurityInterceptor in the next section, but for now we just need to know that it produces Java exceptions and knows nothing about HTTP or how to go about authenticating a principal. Instead the ExceptionTranslationFilter offers this service, with specific responsibility for either returning error code 403 (if the principal has been authenticated and therefore simply lacks sufficient access - as per step seven above), or launching an AuthenticationEntryPoint (if the principal has not been authenticated and therefore we need to go commence step three).併發

ExceptionTranslationFilter是一個Spring安全過濾器,它負責檢測拋出的任何Spring安全異常。此類異常一般由AbstractSecurityInterceptor拋出,它是受權服務的主要提供者。咱們將在下一節討論AbstractSecurityInterceptor,可是如今咱們只須要知道它會產生Java異常,而且不知道HTTP或如何對主體進行身份驗證。相反ExceptionTranslationFilter提供這種服務,具體負責返回錯誤代碼403(若是校長已通過身份驗證的,所以只是缺少足夠的訪問——按步驟7),或啓動一個AuthenticationEntryPoint(若是委託人尚未通過身份驗證的,所以咱們要開始第三步)。app

AuthenticationEntryPoint

The AuthenticationEntryPoint is responsible for step three in the above list. As you can imagine, each web application will have a default authentication strategy (well, this can be configured like nearly everything else in Spring Security, but let’s keep it simple for now). Each major authentication system will have its own AuthenticationEntryPoint implementation, which typically performs one of the actions described in step 3.less

AuthenticationEntryPoint負責上述列表中的第三步。正如您能夠想象的那樣,每一個web應用程序都有一個默認的身份驗證策略(這個策略能夠像Spring Security中的幾乎全部其餘策略同樣配置,可是如今讓咱們保持簡單)。每一個主要的身份驗證系統都有本身的AuthenticationEntryPoint實現,它一般執行步驟3中描述的操做之一。ide

Authentication Mechanism

Once your browser submits your authentication credentials (either as an HTTP form post or HTTP header) there needs to be something on the server that "collects" these authentication details. By now we’re at step six in the above list. In Spring Security we have a special name for the function of collecting authentication details from a user agent (usually a web browser), referring to it as the "authentication mechanism". Examples are form-base login and Basic authentication. Once the authentication details have been collected from the user agent, an Authentication "request" object is built and then presented to the AuthenticationManager.

一旦瀏覽器提交了身份驗證憑證(以HTTP表單post或HTTP header的形式),服務器上就須要「收集」這些身份驗證細節。到目前爲止,咱們已經完成了上述列表中的第6步。在Spring Security中,咱們爲從用戶代理(一般是web瀏覽器)收集身份驗證細節的功能取了一個特殊的名稱,將其稱爲「身份驗證機制」。示例是基於表單的登陸和基自己份驗證。從用戶代理收集身份驗證詳細信息以後,將構建身份驗證「請求」對象,而後將其呈現給AuthenticationManager。

After the authentication mechanism receives back the fully-populated Authentication object, it will deem the request valid, put the Authentication into the SecurityContextHolder, and cause the original request to be retried (step seven above). If, on the other hand, the AuthenticationManager rejected the request, the authentication mechanism will ask the user agent to retry (step two above).

身份驗證機制接收到完整填充的身份驗證對象後,將認爲請求有效,將Authentication放入SecurityContextHolder中,並致使從新嘗試原始請求(上面的步驟7)。另外一方面,若是AuthenticationManager拒絕請求,身份驗證機制將要求用戶代理重試(上面的步驟2)。

Storing the SecurityContext between requests

在請求之間存儲SecurityContext

Depending on the type of application, there may need to be a strategy in place to store the security context between user operations. In a typical web application, a user logs in once and is subsequently identified by their session Id. The server caches the principal information for the duration session. In Spring Security, the responsibility for storing the SecurityContext between requests falls to the SecurityContextPersistenceFilter, which by default stores the context as an HttpSession attribute between HTTP requests. It restores the context to the SecurityContextHolder for each request and, crucially, clears the SecurityContextHolder when the request completes. You shouldn’t interact directly with the HttpSession for security purposes. There is simply no justification for doing so - always use the SecurityContextHolder instead.

根據應用程序的類型,可能須要適當的策略來存儲用戶操做之間的安全上下文。在典型的web應用程序中,用戶登陸一次,而後由其會話Id標識。在Spring Security中,在請求之間存儲SecurityContext的責任落在SecurityContextPersistenceFilter身上,它在默認狀況下將上下文做爲HTTP請求之間的HttpSession屬性存儲。它將每一個請求的上下文恢復到SecurityContextHolder,最重要的是,在請求完成時清除SecurityContextHolder。出於安全目的,您不該該直接與HttpSession交互。這樣作沒有任何理由——老是使用SecurityContextHolder

Many other types of application (for example, a stateless RESTful web service) do not use HTTP sessions and will re-authenticate on every request. However, it is still important that the SecurityContextPersistenceFilter is included in the chain to make sure that the SecurityContextHolder is cleared after each request.

許多其餘類型的應用程序(例如,無狀態RESTful web服務)不使用HTTP會話,而是對每一個請求從新進行身份驗證。可是,仍然須要在鏈中包含SecurityContextPersistenceFilter,以確保在每一個請求以後清除SecurityContextHolder

In an application which receives concurrent requests in a single session, the same SecurityContext instance will be shared between threads. Even though a ThreadLocal is being used, it is the same instance that is retrieved from the HttpSession for each thread. This has implications if you wish to temporarily change the context under which a thread is running. If you just use SecurityContextHolder.getContext(), and call setAuthentication(anAuthentication) on the returned context object, then the Authentication object will change in all concurrent threads which share the same SecurityContext instance. You can customize the behaviour of SecurityContextPersistenceFilter to create a completely new SecurityContext for each request, preventing changes in one thread from affecting another. Alternatively you can create a new instance just at the point where you temporarily change the context. The method SecurityContextHolder.createEmptyContext() always returns a new context instance.
在一個在單個會話中接收併發請求的應用程序中,相同的SecurityContext實例將在線程之間共享。儘管使用的是ThreadLocal,可是從HttpSession中爲每一個線程檢索的實例是相同的。若是您但願臨時更改線程所運行的上下文,那麼這將產生影響。若是您只是使用 SecurityContext.getcontext(),並對返回的上下文對象調用setAuthentication(anAuthentication),那麼身份驗證對象將在共享相同SecurityContext實例的全部併發線程中發生變化。您能夠自定義 SecurityContextPersistenceFilter的行爲,爲每一個請求建立一個全新的SecurityContext,防止一個線程中的更改影響另外一個線程。或者,您能夠只在臨時更改上下文的地方建立一個新實例。方法 SecurityContextHolder.createemptycontext()老是返回一個新的上下文實例。
相關文章
相關標籤/搜索