Shiro官方文檔翻譯——Java Authentication Guide with Apache Shiro

  • 2019 年 10 月 30 日
  • 筆記

Java Authentication Guide with Apache Shiro

Authentication is the process of identity verification– you are trying to prove a user is who they say they are. To do so, a user needs to provide some sort of proof of identity that your system understands and trust.

The goal of this guide is to walk you through how Authentication in Java is performed in Shiro. If you haven』t already please take moment and go through Shiro』s 10 Minute Tutorial so that you get a basic understanding of how to work with Shiro.

Apache Shiro Java 認證教程 Authentication是一個身份驗證過程——你需要證明一個用戶就是他們說的那個。所以這樣做,一個用戶需要提供某種身份證明讓你的系統理解並信任。 這個教程的目標是引導你了解在Shiro中,Authentication在java中是如何執行的。如果你還沒有查看Shiro』s 10 Minute Tutorial,你需要花幾分鐘通過這個教程,它會讓你對Shiro是如何工作的有個基本的理解。

Terminology you』ll need

  • Subject – Security specific user 『view』 of an application user. It can be a human being, a third-party process, a server connecting to you application application, or even a cron job. Basically, it is anything or anyone communicating with your application.
  • Principals – A subjects identifying attributes. First name, last name, social security number, username
  • Credentials – secret data that are used to verify identities. Passwords, Biometric data, x509 certificates,
  • Realms – Security specific DAO, data access object, software component that talks to a backend data source. If you have usernames and password in LDAP, then you would have an LDAP Realm that would communicate with LDAP. The idea is that you would use a realm per back-end data source and Shiro would know how to coordinate with these realms together to do what you have to do.

你需要記住的術語

  • Subject:一個應用程式用戶的具體安全性的用戶視圖。它可能是一個人類,一個第三方流程,一個連接你應用程式的服務程式,甚至是一個定時任務。基本上,它是和你應用程式相連的任何事物或任何人。
  • Principals:一個subjects的確認屬性。姓、名、身份證號、用戶名。
  • Credentials:用於認證身份的神秘數據。密碼、生物特徵數據、x509證書。
  • Realms:安全性具體的DAO(數據訪問對象),與後端數據源對話的軟體組件。如果你在LDAP(輕量級數據訪問協議)存在usernames和password,然後你就有一個LDAP Realms,它將會與LDAP通訊。這個想法是,你需要一個realm後端端數據源,Shiro會知道如何協調這些Realms在一起,做你必須做的。

How to Authenticate in Java with Shiro

In Shiro』s framework, and most every other framework for that matter, the Java authentication process can be broken up into three distinct steps.

Steps

  1. Collect the subject』s principals and credentials
  2. Submit the principals and credentials to an authentication system.
  3. Allow access, retry authentication, or block access

Here is some code on how you do this in Shiro Specifically.

Shiro在java中是如何認證的 在Shiro框架中,或者針對這個問題的大多數其它框架,Java認證過程可以分成三個不同的步驟。 步驟

  1. 採集subject的principals和credentials。
  2. 提交principals和credentials到一個認證系統。
  3. 允許訪問,返回認證,或不允許訪問。

這裡是在Shiro中你如何執行以上步驟的程式碼。

Step1 – Collect the subject's principals and credentials

//Example using most common scenario:  //String username and password.  Acquire in  //system-specific manner (HTTP request, GUI, etc)  UsernamePasswordToken token = new UsernamePasswordToken( username, password );  ​  //」Remember Me」 built-in, just do this:  token.setRememberMe(true);

In this particular case, we』re using a class called UsernamePasswordToken. It is the most common authentication token used in the framework.

We use this token to bundle the username and password we acquired in someway in our Java application. Maybe they were submitted via a user web form, an HTTP header, or a command line. In Shiro, it does not matter how you acquire them– it is protocol agnostic.

In this example, we have decided that we want the application to remember users when they return. So once the token is created, we use Shiro』s built-in 「Remember-me」 feature by setting it to true on the token. This is done using the token』s setRememberMe() method

在這個特別的案例中,我們使用了一個叫UsernamePasswordToken的類。在框架中,它是最通用的認證令牌。 我們使用這些令牌去綁定在我們java應用程式中通過某種方式獲得的賬戶名和密碼。也許他們是被提交的用戶表單,一個http請求頭,一個命令行。在Shiro,怎麼去獲取它不是一個問題——它們與協議無關。 在這個例子中,我們決定當應用程式返回用戶資訊前記住它們。所以一旦令牌被創建,我們使用Shiro內置的「Remember-me」特徵並設置為true。它使用token的setRememberMe()方法。

Step 2 – Submit the principals and credentials to an authentication system.

So we』ve collected the information in a token and set it to remember returning users. The next step is in the Authentication process is to submit the token to an authentication system. Your authentication system is represented in Shiro by security-specific DAOs, that are referred to as Realms. For more information on realms please check out the Shiro Realm Guide.

In Shiro we try to make this part as quick and easy as humanly possible. We have it down to one line of Java code!

因此,我們採集了令牌資訊,並設置它去記住返回的用戶。認證過程的下一步是提交令牌去一個認證系統。你的認證系統在Shiro中的代表是安全的具體DAOs,它們被引用稱為Realms。更多realms的資訊請點擊 Shiro Realm Guide。 在Shiro中,我們試圖使這部分儘可能的快速和簡單。我們已經把它用一行程式碼完成。

//With most of Shiro, you'll always want to make sure you're working with the currently  //executing user, referred to as the subject  Subject currentUser = SecurityUtils.getSubject();  ​  //Authenticate the subject by passing  //the user name and password token  //into the login method  currentUser.login(token);

First, we need to acquire the currently executing user, referred to as the subject. A subject is just a security specific view of the user—-it can be a human, a process, cron job, doesn』t matter. In Shiro, there is always a subject instance available to the currently executing thread. The concept of a subject is core to Shiro and most of the framework is centered around working with subjects. In this example, we will name this instance of subject currentUser.

To acquire the subject, we use the SecurityUtils class which is also a core pat of Shiro』s API. It will acquire the currently executing user via the getsubject() method call. And we get back a subject instance that is representing who the current user is who is interacting with the system. At this point in the example, the subject currentUser is anonymous. There is no identity associated with them.

Now with the user representation in hand, we authenticate them by just calling the login()) method and submit the token we just constructed a second ago.

首先,我們需要獲得當前存在的用戶,把它當做subject引用。一個subject僅僅是一個用戶的安全具體視圖——它可能是一個人、一個處理、定時任務,都沒有問題。在Shiro中,這裡總會有一個subject實例可以從當前存在的執行緒中獲得。subject的概念是Shiro的核心,幾乎所有的框架都是圍繞subject工作的。在這個例子中,我們將這個subject實例命名為currentUser。 去獲得subject,我們使用SecurityUtils類,它也是Shiro的API的一個主要成分。它獲得當前存在的用戶通過調用getsubject()方法。我們得到返回的一個subject實例,它是與系統交互的當前用戶的代表。在例子的這個點,currentUser這個subject是匿名的。它沒有與之相關的身份。 現在有關係的代表用戶,我們認證它們通過調用login()方法,並且提交我們一秒前構建的token。

Step 3 – Allow access, retry authentication, or block access

Again really, really easy, single method call. If the login() method call is successful, then the user is logged in and associated with a user account or identity. From here, the user can go about using your application and retain their identity through their session or longer since we have set the 「Remember Me」 in our example.

But what happens if something fails in the authentication attempt? What if they give you the wrong password or they accessed the system too many times, maybe their account is locked? In this case, Shiro will throw an exception. This is where Shiro』s rich exception hierarchy comes into play.

再次,真的,真的很簡單,單方法調用。如果login()方法調用成功,借著用戶被登錄,並包括與用戶相關聯的賬戶或身份。從這裡,用戶可以在應用程式中被使用,和保存它們的身份通過它們的session或者使用不久前學過的我們設置"Remember me"的例子。 但是,如果在驗證嘗試中,一些東西失敗了會發生什麼呢?如果他們給你錯誤的密碼或者他們訪問系統太長時間了,也許他們賬戶被鎖了會怎麼樣呢?在這個例子,Shiro將拋出一個異常。這裡就是Shiro豐富層次的異常。

try {      currentUser.login(token);  } catch  ( UnknownAccountException uae ) { ...  } catch  ( IncorrectCredentialsException ice ) { ...  } catch  ( LockedAccountException lae ) { ...  } catch  ( ExcessiveAttemptsException eae ) { ...  } ...  your own ...  } catch ( AuthenticationException ae ) {      //unexpected error?  }  //No problems, show authenticated view…

You can take that method call and wrap it in a try/catch block and you can catch all sort of exceptions if you want to handle them and react accordingly. In addition to a rich set of exceptions that Shiro offers, you can create your own if you need custom functionality. For more information, follow this link documentation on AuthenticationException.

你能調用這個方法,等待它進入try/catch模組,你就能捕獲所有類型的異常,如果你想要處理它們並做出相應反應。除了Shiro提供的富有的異常設置,你可以創建你自己的自定義功能異常。更多資訊,請進入這個文檔的鏈接AuthenticationException

Security Tip Security best practice is to give generic login failure messages to users because you do not want to aid an attacker trying to break into your system.

安全性小提示 安全性最好的練習是給通用的登錄失敗提示資訊到用戶,應為你不想幫助一名黑客嘗試打破並進入你的系統。

「Remember Me」 Support

As shown in the example above, Shiro supports the notion of 「remember me」 in adition to the normal login process.

In Shiro, the Subject object supports two methods : isRemembered() and isAuthenticated().

A 「remembered」 subject has an identity (it is not anonymous) and their identifying attributes,referred to as principals, are remembered from a successful authentication during a previous session.

An authenticated subject has proved their identity during their current session.

"Remember Me"支援 在上面例子所展示的,Shiro在正常的登錄過程中支援「remember me」的概念。 在Shiro,subject對象支援兩個方法:isRemembered()isAuthenticated()。 一個「remembered」subject有身份(不是匿名)和它們的確認屬性,被引用成principals,在前一個session中,一個成功的認證的subject會被記住。 一個認證subject已經在當前執行緒中被證實身份。

Warning If a subject is remembered, it DOES NOT mean they are authenticated.

警告 如果一個subject被記住,並不代表它被驗證.

Remembered vs Authenticated

In shiro it is very important to note that a remembered subject is not an authenticated subject. A check against isAuthenticated() is a much more strict check because authentication is the process of proving you are who you say you are. When a user is only remembered, the remembered identity gives the system an idea who that user probably is, but in reality, has no way of absolutely guaranteeing if the remembered Subject represents the user currently using the application. Once the subject is authenticated, they are no longer considered only remembered because their identity would have been verified during the current session.

So although many parts of the application can still perform user-specific logic based on the remembered principals, such as customized views, it should never perform highly-sensitive operations until the user has legitimately verified their identity by executing a successful authentication attempt.

For example, a check to see if a subject can access financial information should almost always depend on isAuthenticated(), not isRemembered(), to guarantee a verified identity.

Here is a scenario to help illustrate why the the distinction between isAuthenticated and isRemembered is important.

Let』s say you』re using Amazon.com. You log in and you add some books to your shopping cart. A day goes by. Of course your user session has expired and you』ve been logged out. But Amazon 「remembers」 you, greets you by name, and is still giving you personalized book recommendations. To Amazon, isRemembered() would return TRUE. What happens if you try to use one of the credit cards on file or change your account information? While Amazon 「remembers」 you, isRemembered() = TRUE, it is not certain that you are in fact you, isAuthenticated()=FALSE. So before you can perform a sensitive action Amazon needs to verify your identity by forcing an authentication process which it does through a login screen. After the login, your identity has been verified and isAuthenticated()=TRUE.

This scenario happens very often over the web so the functionality is built into Shiro helping you easily make the distinction yourself.

Remembered 和 效驗 在shiro,有一個非常重要的地方需要記下,一個remembered的subject不是一個authenticated的subject。一個核對isAuthenticated()是一個更嚴格的檢查因為authentication是一個證明你是你說的你的過程。當一個用戶只是remembered,這個remembered的身份給予系統一個主意,那個用戶可能是哪個,但是現實中,沒有辦法保證快取的Subject代表的用戶是當前應用程式使用的用戶。一旦subject驗證通過,它會不再考慮僅僅快取,因為它的身份在噹噹前執行緒已經被證實了。 所以通過應用程式的許多部分仍能執行用戶具體的邏輯基於快取的principals,比如訂製的視圖,它不允許執行高度敏感的操作直到用戶擁有合法已證實的身份在它執行一次成功的認證嘗試之後。 舉個例子,一個查看的檢查,如果一個subject能訪問財務資訊幾乎都依賴isAuthenticated()而不是isRemembered(),去保證一個已證實的身份。 這裡有一個腳本來幫助說明為什麼isAuthenticatedisRemembered的區別是重要的。 讓我們說你正在使用Amazon.com。你登錄並且添加了一些書在你的購物車。一天過去了。當然你的用戶已過期並且你被註銷了。但是亞馬遜"remembers"你,問候了你的名字,並且還在給你個性化的書籍推薦。對於亞馬遜,isRemembered()將會返回TRUE。如果你試圖使用一張列表上的信用卡或者修改用戶資訊會發生什麼?當亞馬遜"remembered"你,isRemembered() = TRUE,不確定你其實是你自己,isAuthenticated()=FALSE。所以之前你能執行一個敏感操作亞馬遜需要強迫執行一次認證過程去確認的身份,如使用一個登錄頁面。登錄後,你的身份被驗證且isAuthenticated()=TRUE。 這種場景在web中經常發生,所以這個紅石在Shiro中建立是幫助你更容易區分你自己。

Logging Out

Finally, when the user is done using the application, they can log out. And in Shiro, we make logging out quick and easy with a single method call.

註銷 最終,當用戶完成應用的操作後,它們能註銷。在Shiro,我們註銷快速又簡單,掉一個單獨方法。

currentUser.logout(); //removes all identifying information and invalidates their session too.

When you log out in Shiro it will close out the user session and removes any associated identity from the subject instance. If you』re using RememberMe in a web environment, then .logout() will, by default, also delete the RememberMe cookie from the browser.

Lend a hand with documentation

While we hope this documentation helps you with the work you're doing with Apache Shiro, the community is improving and expanding the documentation all the time. If you'd like to help the Shiro project, please consider corrected, expanding, or adding documentation where you see a need. Every little bit of help you provide expands the community and in turn improves Shiro.

The easiest way to contribute your documentation is to submit a pull-request by clicking on the Editlink below, send it to the User Forum or the User Mailing List.

當你在Shiro中註銷它,它會關閉用戶session,移除任何相關身份從subject實例中。如果你使用RememberMe在web環境中,當.logout()執行,默認情況,也會刪除RememberMe的快取在瀏覽器上的。 文檔幫助 當我們希望文檔幫助你工作當你正在使用Apache Shiro,社區總會改善和擴大文檔。如果你喜歡幫助Shiro項目,請考慮修正、擴大、或增加文檔當你認為需要的。任何一點小的幫助都能提供社區擴大,並提升Shiro。最容易的方式是貢獻你的文檔,提交一個拉請求通過點擊在下面的Edit鏈接,發送它到用戶論壇或用戶郵件列表。