使用Spring Security,Thymeleaf和Okta保护Java应用程序的安全
永不再構建身份驗證 –喜歡構建用戶管理? 使用Okta,您可以在幾分鐘內為您的應用程序添加社交登錄,多因素身份驗證和OpenID Connect支持。 立即創建一個免費的開發者帳戶。
在構建Java應用程序時,用戶管理是至關重要的考慮因素。 應用程序和API通常會根據分配給用戶的角色來劃分對應用程序不同部分的訪問權限-這是基于角色的訪問控制(RBAC)。
這就是Okta的用處– Okta通過管理組內的角色(用戶可以屬于一個或多個組)來簡化此過程。 借助Okta的Spring Security集成,該過程通過使用將組映射到特定角色并允許或拒絕訪問的通用注釋而變得自動化。 這是使用常見的Spring Security注釋完成的,我們在下面對此進行了概述。
為了在實踐中展示這一點,我在下面整理了一個演示,演示了一個簡單但常見的場景。 在我們的示例中,我們將查看未受保護的頁面,只有經過身份驗證的用戶才能訪問的頁面以及要求用戶在訪問它們之前必須具有額外授權級別的頁面的混合。
我們在這里添加了我們引用的所有代碼。
如果您已經打算開始使用Java應用程序的內置RBAC并開始使用它,只需在此處將Okta租戶連接到Spring Boot應用程序即可。
如有任何疑問,請在此處聯系Okta的開發支持團隊。
第一步:配置您的Okta帳戶
第一步是設置Okta租戶。 這樣,您可以啟動我們創建的示例應用程序,并在實際中看到它。 在此處注冊開發者帳戶,然后按照以下步驟操作:
讓我們來看一下它是什么樣的:
設置組
在您的Okta管理員儀表板菜單中,找到“ Users ,然后單擊“ Groups 。 單擊Add Group然后在Name字段中輸入admins ,然后添加組描述,例如:管理員。 單擊Add Group以完成此步驟。
按照相同的過程添加users組。
設置用戶
再次,在Okta Admin儀表板中導航至Users ,但這一次單擊People 。 單擊Add User然后在表單中填寫用戶信息。 (將真實的電子郵件地址用作主電子郵件地址或輔助電子郵件地址,以及您可以訪問的電子郵件地址,以便以后可以驗證電子郵件。)在“ Groups字段中,將此用戶添加到您先前創建的users組中。 確保已單擊Send user activation email now復選框,然后單擊“保存并添加另一個”。
我們重復上述步驟,只是這一次,第二用戶添加到兩個 users和admins組。
跳到您的電子郵件并驗證這些電子郵件地址。 單擊兩個用戶的鏈接以激活它們。
創建一個OIDC應用程序
現在是時候設置您的身份驗證層了。
在Okta Admin儀表盤中,單擊菜單中的Applications ,然后單擊Add Application 。
選擇Web ,然后單擊Next 。
當提示您填寫表格時,請使用以下值:
| Field?????????????? | Value????????????????????????? | | ------------------- | ------------------------------ | | Name??????????????? | Fun with Spring Security Roles | | Base URIs?????????? | http://localhost:8080/???????? | | Login redirect URIs | http://localhost:8080/???????? | | Group assignments?? | `admins` and `users`?????????? | | Grant type allowed? | Check: `Implicit`????????????? |準備就緒后,單擊“完成”,您將在下面看到結果頁面:
小費
指定的URI是Spring Boot的默認值。 您以后可以輕松更改它們。
繼續進行下一步之前,向下滾動并記下Client ID 。 您將需要它來配置Spring Boot應用程序。
設置授權服務器
接下來,在Okta管理員儀表板菜單中查找API ,然后單擊Authorization Servers以啟動以下命令:
記下Issuer URI 。 稍后您還將需要此配置Spring Boot應用程序。
單擊default然后選擇“ Claims選項卡。 單擊Add Claim然后按如下所示填寫字段:
| Field???????????????? | Value??????? | | --------------------- | ------------ | | Name????????????????? | groups?????? | | Include in token type | Access Token | | Value type??????????? | Groups?????? | | Filter??????????????? | Regex .*???? | | Include in??????????? | Any scope??? |單擊Create以完成此步驟。
創建此聲明可確保在用戶進行身份驗證時將組成員身份信息包括在訪問令牌中。 這一步對于了解Spring Security的角色和權限機制至關重要。
第二步:配置您的Spring Boot應用
首先,在此鏈接處克隆。
在首選的IDE或編輯器中打開項目。 下面的截圖來自這里。
復制application.yml.sample文件并將其命名為application.yml
還記得我們標記要保存的那些值嗎? 使用這些更新您的信息。 這是我們的示例:
| Name??????? | Value???????????????????????????????????????????? | | ----------- | ------------------------------------------------- | | baseUrl???? | https://dev-237330.oktapreview.com??????????????? | | issuer????? | https://dev-237330.oktapreview.com/oauth2/default | | audience??? | api://default???????????????????????????????????? | | clientId??? | 0oacdldhkydGGruON0h7????????????????????????????? | | rolesClaim? | groups??????????????????????????????????????????? | | redirectUri | http://localhost:8080/??????????????????????????? |在進入代碼之前,讓我們看看實際的應用程序。
從命令行運行此命令以開始操作:
mvn spring-boot:run查看實際應用
導航到主頁,然后單擊“ Login 。
要登錄,請使用屬于您在第一步中創建的“ Users組的用戶的憑據。 從那里,您將看到該應用程序顯示您的用戶信息,并在其下方顯示一行按鈕。
這些與應用程序內的訪問權限相對應。 單擊“ Users Only時, users組的成員將能夠看到該頁面。 對于admins組的用戶,情況相同,單擊“ Admins Only時可以看到該頁面。
讓我們看看它是如何工作的。
單擊Users Only 。 您會看到一個頁面,顯示您是users組的成員。
單擊上Back ,然后單擊Admins Only 。 這次,您將獲得403 Unauthorized頁面,因為您不是admins組的成員。
單擊Logout并再次登錄,但是這次是屬于兩個組的用戶(您在步驟1中創建的第二個用戶)。 單擊Admins Only 。
這次,您將看到您同時屬于admins和users組。
很簡單! 現在,讓我們跳入代碼...
第三步:Spring安全代碼審查
本節概述Okta組如何鏈接到Spring Security角色。
該演示應用程序使用以下內容:
我們依賴okta-spring-security-starter (來自pom.xml)。 這就是幕后魔術的發生方式:
... <dependency><groupId>com.okta.spring</groupId><artifactId>okta-spring-security-starter</artifactId><version>0.1.0</version> </dependency> ...讓我們從Javascript Okta登錄小部件開始,看看它如何將客戶端連接到Spring Boot。
設置Okta登錄小部件
這是我們在`login.html` Thymeleaf模板中設置Okta登錄小部件的方式:
$( document ).ready(function() {var data = {baseUrl: [[${appProperties.baseUrl}]],clientId: [[${appProperties.clientId}]],redirectUri: [[${appProperties.redirectUri}]],authParams: {issuer: [[${appProperties.issuer}]],responseType: ['token']}};window.oktaSignIn = new OktaSignIn(data);// Check if we already have an access tokenvar token = oktaSignIn.tokenManager.get('token');if (token) {window.location.href = "/authenticated";} else {renderWidget();} });在第3-8行中,您將看到我們已經嵌入了所有設置以作為嵌入式Thymeleaf Template變量連接到Okta租戶。 這些值從Spring Boot控制器作為模型的一部分傳入。 這樣,您只需指定一次這些設置-現在服務器端和客戶端都可以確保它們。 我們將在下面詳細說明如何管理這些設置(它們全部來自application.yml文件)。
在配置并實例化Okta登錄小部件之后,下一步是檢查用戶是否已登錄。然后執行以下兩個操作之一。 如果有,我們將其發送到/authenticated頁面。 如果還沒有,我們將渲染小部件,這將為用戶提供登錄的機會。
這是renderWidget函數:
function renderWidget() {oktaSignIn.renderEl({el: '#okta-login-container'},function (response) {// check if successif (response.status === 'SUCCESS') {// for our example we have the id token and the access tokenoktaSignIn.tokenManager.add('token', response[0]);if (!document.location.protocol.startsWith('https')) {console.log('WARNING: You are about to pass a bearer token in a cookie over an insecure\n' +'connection. This should *NEVER* be done in a production environment per\n' +'https://tools.ietf.org/html/rfc6750');}document.cookie = 'access_token=' + oktaSignIn.tokenManager.get('token').accessToken;document.location.href = "/authenticated";}},function (err) {// handle any errorsconsole.log(err);}); }在窗口小部件上呈現了窗口小部件之后,內部邏輯將根據用戶登錄時的設置來接管。在這種情況下,您正在使用此流,并且僅獲取由配置的responseType參數指定的訪問令牌。 。
成功登錄后,您將輸入帶有response對象的回調函數。 響應對象具有您的訪問令牌(在本例中為您用戶的訪問令牌)。
第19行使用訪問令牌設置cookie,第20行將(現在已認證的)用戶發送到/authenticated端點。
此時,Spring Security可以識別經過身份驗證的用戶。
在介紹Spring Security角色之前,讓我們看一下Spring Security如何處理訪問令牌。
Spring Security令牌提取器
默認情況下,Spring Security OAuth 2.0插件處理進入Authorization標頭中的訪問令牌作為承載令牌。 這對于為客戶端(例如Angular客戶端)創建RESTful響應的應用程序很好。
對于此示例,我將Javascript的體系結構和數量保持在最低限度,因此我希望進行完整的頁面轉換。 這有點老套了,但是它使示例代碼緊湊而緊湊。
為了使Spring Security能夠識別用戶已通過身份驗證,我們需要它能夠處理進入cookie的令牌。
幸運的是,通過設置TokenExtractor ,Spring Security使覆蓋默認行為變得非常容易。 這是從OktaSpringSecurityRolesExampleApplication實現此目的的代碼:
@Bean protected ResourceServerConfigurerAdapter resourceServerConfigurerAdapter() {return new ResourceServerConfigurerAdapter() {...@Overridepublic void configure(ResourceServerSecurityConfigurer resources) throws Exception {resources.tokenExtractor(new TokenExtractor() {@Overridepublic Authentication extract(HttpServletRequest request) {String tokenValue = findCookie(ACCESS_TOKEN_COOKIE_NAME, request.getCookies());if (tokenValue == null) { return null; }return new PreAuthenticatedAuthenticationToken(tokenValue, "");}...});}}; }這樣做是從傳入請求的Cookie列表中提取訪問令牌(如果可以)。 然后,將自動完成解析和驗證。 瞧!
建立基于角色的訪問控制
在應用程序設置中,您定義打開哪些路徑。 所有其他路徑至少需要經過身份驗證的會話。
這是OktaSpringSecurityRolesExampleApplication的另一個摘錄:
@Bean protected ResourceServerConfigurerAdapter resourceServerConfigurerAdapter() {return new ResourceServerConfigurerAdapter() {@Overridepublic void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/", "/login", "/images/**").permitAll().and().exceptionHandling().accessDeniedHandler(customAccessDeniedHandler);}...}; }在這種情況下,您要告訴Spring Security允??許任何未經身份驗證的用戶訪問主頁( / ),登錄頁面( /login )以及任何來自靜態圖像文件夾的內容。 這意味著默認情況下會自動限制所有其他路徑。
此時,您還定義了一個自定義的訪問拒絕處理程序。
@Controller public class SecureController {@Autowiredprotected AppProperties appProperties;@RequestMapping("/authenticated")public String authenticated(Model model) {model.addAttribute("appProperties", appProperties);return "authenticated";}@RequestMapping("/users")@PreAuthorize("hasAuthority('users')")public String users() {return "roles";}@RequestMapping("/admins")@PreAuthorize("hasAuthority('admins')")public String admins() {return "roles";}@RequestMapping("/403")public String error403() {return "403";} }在此控制器中,我們定義了四個路徑,所有這些路徑都至少需要經過身份驗證的用戶。
真正的價值來自/users和/admins路徑。 請注意,它們都具有@PreAuthorize批注。 這意味著, 在隨后的表達必須在方法之前應滿足甚至會被輸入。 hasAuthority函數確認經過身份驗證的用戶是否屬于那些角色。 在此示例中,這些自動映射到我們之前創建的Okta組,這就是為什么在Okta的訪問令牌中包含groups聲明很重要的原因。
盡管這涉及到一些設置,但是現在您僅需一行代碼即可實現基于角色的訪問控制!
端到端配置
在客戶端,我們從應用程序本身提供了一組Thymeleaf模板形式HTML頁面。 因此,有一個單一的來源來提供客戶端和服務器所需的配置值是有意義的。
使用Spring的@Component和@ConfigurationProperties批注很容易。
這是AppProperties類:
@Component @ConfigurationProperties("okta.oauth") public class AppProperties {private String issuer;private String audience;private String clientId;private String rolesClaim;private String baseUrl;private String redirectUri;... getters and setters ... }@ConfigurationProperties告訴Spring從application.yml文件中okta.oauth屬于okta.oauth密鑰的所有屬性。
@Component注釋使Spring實例化此Object并使它可用于其他地方的自動裝配。
看一下HomeController這段代碼:
@Controller public class HomeController {@Autowiredprotected AppProperties appProperties;...@RequestMapping("/login")public String login(Model model) {model.addAttribute("appProperties", appProperties);return "login";} }在單擊/login端點時返回login視圖之前,將AppProperties對象(在第4和5行自動AppProperties )添加到模型中。
這就是使它可用于Thymeleaf模板的原因:
<script th:inline="javascript">/*<![CDATA[*/$( document ).ready(function() {var data = {baseUrl: [[${appProperties.baseUrl}]],clientId: [[${appProperties.clientId}]],redirectUri: [[${appProperties.redirectUri}]],authParams: {issuer: [[${appProperties.issuer}]],responseType: ['token']}};window.oktaSignIn = new OktaSignIn(data);...});.../*]]>*/ </script>開始編碼!
就是這樣! 試一試,讓我知道它的進展! 我在Twitter上。
雖然我已經概述了將Okta的Groups機制與Spring Security的基于角色的訪問控制結合使用的好處,但Okta的Java開發團隊仍在努力開發我們的下一代SDK和集成。 請隨時注意新的Okta Java Spring Boot Integration的即將發布的版本,該版本將支持其他OIDC工作流程,包括code以及托管的,可配置的登錄和注冊視圖。
該帖子已從此處改編。
永不再構建身份驗證 –喜歡構建用戶管理? 使用Okta,您可以在幾分鐘內為您的應用程序添加社交登錄,多因素身份驗證和OpenID Connect支持。 立即創建一個免費的開發者帳戶。
翻譯自: https://www.javacodegeeks.com/2017/11/secure-java-app-spring-security-thymeleaf-okta.html
總結
以上是生活随笔為你收集整理的使用Spring Security,Thymeleaf和Okta保护Java应用程序的安全的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 九八一事变简介50字 关于九八一事变简介
- 下一篇: 咕组词 咕如何组词