<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                ### 1. 概述 本文中,我們來看看[Apache Shiro](https://shiro.apache.org/),一種通用Java安全框架。 該框架高可定制且模塊化,提供authentication(身份驗證),authorization(授權),cryptography(加密)和sesion management(會話管理)。 ### 2. 依賴 Apache Shiro有如此多的[modules](https://shiro.apache.org/download.html)。然而,在本教程中,我們只使用*shiro-core* artifact。 將它添加到我們的*pom.xml*: ~~~ <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.4.0</version> </dependency> ~~~ 最新版的 Apache Shiro modules可以再[Maven中心](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22org.apache.shiro%22)找到。 ### 3.配置安全管理 *SecurityManager*是Apache Shiro框架的核心部分,在運行時通常只會有一個實例。 在本教程中,我們桌面環境探討框架。為了配置框架,我們需要在resource文件夾中創建一個*shiro.ini*文件,內容如下: ~~~ [users] user = password, admin user2 = password2, editor user3 = password3, author [roles] admin = * editor = articles:* author = articles:compose,articles:save ~~~ *shiro.ini*配置文件中的[users]部分定義了供*SecurityManager*識別的用戶憑證。格式為:principal (username) = password, role1, role2, …, role。 角色與其關聯的權限在[roles]中定義。*admin*角色被賦予了應用全部訪問權限。使用通配符(*)標識。 *editor*角色擁有“文章”下的全部權限,然而*author*角色只能編寫和保存“文章”。 *SecurityManager*用于配置*SecurityUtils*類。從*SecurityUtils*中我們可以獲取當前用戶與系統的交互, 并執行身份驗證和授權操作。 讓我們使用*IniRealm*從*shiro.ini*文件中加載我們用戶和角色定義,并使用它來配置*DefaultSecurityManager*對象: ~~~ IniRealm iniRealm = new IniRealm("classpath:shiro.ini"); SecurityManager securityManager = new DefaultSecurityManager(iniRealm); SecurityUtils.setSecurityManager(securityManager); Subject currentUser = SecurityUtils.getSubject(); ~~~ 現在我們持有一個知道*shrio.ini*文件所定義的用戶憑證和角色的*SecurityManager*。讓我們接著進行用戶認證和授權。 ### 4.身份驗證 在Apache Shiro的術語中,*Subject*是一種與系統交互的任意實體。可能是一個人,一個腳本,或者一個REST客戶端。 調用*SecurityUtils.getSubject()*返回一個當前*Subject*實例,即*currentUser*。 既然已有*currentUser*對象。我們可以執行身份認證基于現有憑證: ~~~ if (!currentUser.isAuthenticated()) { UsernamePasswordToken token = new UsernamePasswordToken("user", "password"); token.setRememberMe(true); try { currentUser.login(token); } catch (UnknownAccountException uae) { log.error("Username Not Found!", uae); } catch (IncorrectCredentialsException ice) { log.error("Invalid Credentials!", ice); } catch (LockedAccountException lae) { log.error("Your Account is Locked!", lae); } catch (AuthenticationException ae) { log.error("Unexpected Error!", ae); } } ~~~ 首先,我們檢查當前用戶是否未曾驗證。然后我們創建一個認證帶有主角(用戶名)和憑證(密碼)的token。 接下來,我們嘗試用token登錄。如果提供的憑證正確,一切順利。 不同情況對應不同的異常。也有可能拋出自定義異常來滿足應用需求。可以通過繼承*AccountException*類來實現。 ### 5.授權 身份認證是嘗試著校驗用戶身份,然而授權是嘗試控制系統某資源的訪問。 回顧下,在我們創建*shiro.ini*文件時我們賦予了一個或多個角色給用戶。而且,在roles部分,我們給每個角色定義了不同權限和訪問級。 現在讓我們~~蕩起雙槳~~看看在我們的應用中實行用戶訪問控制怎樣使用。 在*shiro.ini*文件中,我們給了*admin*全部系統權限,*editor*擁有關于文章每個資源/操作全部權限,并且*author*被限制只能編寫和保存文章的權限。 讓我們基于角色歡迎當前用戶: ~~~ if (currentUser.hasRole("admin")) { log.info("Welcome Admin"); } else if(currentUser.hasRole("editor")) { log.info("Welcome, Editor!"); } else if(currentUser.hasRole("author")) { log.info("Welcome, Author"); } else { log.info("Welcome, Guest"); } ~~~ 現在,讓我們看看當前用戶在系統里允許做什么: ~~~ if(currentUser.isPermitted("articles:compose")) { log.info("You can compose an article"); } else { log.info("You are not permitted to compose an article!"); } if(currentUser.isPermitted("articles:save")) { log.info("You can save articles"); } else { log.info("You can not save articles"); } if(currentUser.isPermitted("articles:publish")) { log.info("You can publish articles"); } else { log.info("You can not publish articles"); } ~~~ ### 6.Realm配置 在真實應用中,我們將需要從數據庫一個得到用戶憑證而不是從*shiro.ini*文件中。這就是*Realm*概念的用武之地。在Apache Shiro術語中,一個[Realm](https://shiro.apache.org/realm.html)就是一個指向存儲用于驗證授權的用戶憑證的DAO。 創建一個realm,我們只需要實現*Realm*接口。這很令人討厭;然而,我們可以繼承框架提供的默認實現。其中一個就是*JdbcRealm*。 我們創建一個自定義realm實現來繼承*JdbcRealm*類并重下以下方法:*doGetAuthenticationInfo(),doGetAuthorizationInfo(),getRoleNamesForUser()和getPermissions()*。 讓我們創建一個繼承*JdbcRealm*類的realm: ~~~ public class MyCustomRealm extends JdbcRealm { //... } ~~~ 為了簡單起見,我們使用*java.util.Map*來模擬一個數據庫: ~~~ private Map<String, String> credentials = new HashMap<>(); private Map<String, Set<String>> roles = new HashMap<>(); private Map<String, Set<String>> perm = new HashMap<>(); { credentials.put("user", "password"); credentials.put("user2", "password2"); credentials.put("user3", "password3"); roles.put("user", new HashSet<>(Arrays.asList("admin"))); roles.put("user2", new HashSet<>(Arrays.asList("editor"))); roles.put("user3", new HashSet<>(Arrays.asList("author"))); perm.put("admin", new HashSet<>(Arrays.asList("*"))); perm.put("editor", new HashSet<>(Arrays.asList("articles:*"))); perm.put("author", new HashSet<>(Arrays.asList("articles:compose", "articles:save"))); } ~~~ 接著我們重寫*doGetAuthenticationInfo()*: ~~~ protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { UsernamePasswordToken uToken = (UsernamePasswordToken) token; if(uToken.getUsername() == null || uToken.getUsername().isEmpty() || !credentials.containsKey(uToken.getUsername())) { throw new UnknownAccountException("username not found!"); } return new SimpleAuthenticationInfo( uToken.getUsername(), credentials.get(uToken.getUsername()), getName()); } ~~~ 我們首先將提供的*AuthenticationToken*強制轉換*UsernamePasswordToken*。從*uToken*,我們提取用戶名(*uToken.getUsername()*) 并且以此從數據庫獲取用戶憑證(密碼)。 如果沒有找到記錄——我們拋出一個*UnknownAccountException*(這里還比較了密碼是否相同,譯者注),否則我們使用用戶名和憑證構成一個*SimpleAuthenticatioInfo*對象然后返回。 如果用戶憑證加鹽哈希(一種加密策略,譯者注),我們需要返回一個帶鹽的*SimpleAuthenticationInfo*: ~~~ return new SimpleAuthenticationInfo( uToken.getUsername(), credentials.get(uToken.getUsername()), ByteSource.Util.bytes("salt"), getName() ); ~~~ 我們也需要重寫*doGetAuthorizationInfo()*,*getRoleNamesForUser()* 和*getPermissions()*。 最后,將自定義realm交給*securityManager*。我們所需做的就是用我們自定義的realm替換*IniRealm*,并且傳給*DefaultSecurityManager*的構造器。 ~~~ Realm realm = new MyCustomRealm(); SecurityManager securityManager = new DefaultSecurityManager(realm); ~~~ 其余部分代碼跟之前相同。這就是我們正確使用自定義realm所需配置的*securityManager*。 現在的問題是——框架如何匹配憑證?缺省的,JdbcRealm使用*SimpleCredentialsMatcher*,它只檢查*AuthenticationToken*和*AuthenticationInfo*中的憑證是否相等。 如果我們哈希我們的密碼。我們需要告知框架使用*HashedCredentialsMatcher *替換。哈希密碼的realm的INI配置可在[這里](https://shiro.apache.org/realm.html#Realm-HashingCredentials)找到。 ### 7.注銷 我們已經認證了用戶,是時候實現注銷了。調用一個簡單的方法就能完成,使得用戶session無效化并且退出: ~~~ currentUser.logout(); ~~~ ### 8.Session管理 框架通常伴隨著session管理系統。如果在web環境使用,默認為HttpSession接口。 對于單應用,它使用企業session管理系統。好處是即使是在桌面環境和典型的web環境,你也可以使用session對象。 讓我們看一個當前用戶session交互的簡單例子: ~~~ Session session = currentUser.getSession(); session.setAttribute("key", "value"); String value = (String) session.getAttribute("key"); if (value.equals("value")) { log.info("Retrieved the correct value! [" + value + "]"); } ~~~ ### 9.Sping Web應用下的Shiro 到目前為止我們概述了Apache Shiro的基本結構,并且我們在桌面環境中實現了。讓我們繼續把框架和Spring Boot應用整合起來。 注意重點在Shiro,而不是Spring應用——我們只用來快速搭建簡單實例app。 #### 9.1.依賴 首先,我們需要添加Spring Boot parent 依賴到我們的*pom.xml*: ~~~ <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.2.RELEASE</version> </parent> ~~~ 接著,我們將以下依賴加到同個*pom.xml*文件里: ~~~ <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-freemarker</artifactId> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring-boot-web-starter</artifactId> <version>${apache-shiro-core-version}</version> </dependency> ~~~ #### 9.2.配置 添加*shiro-spring-boot-web-starter*依賴到我們的*pom.xml*里將默認配置一些Apache Shiro應用的特性,比如*SecurityManager*。 然而,我們仍需要配置*Realm *和*Shiro security*過濾器。我們將 和上邊一樣的自定義realm。 因此,在Spring Boot應用運行主類上,我們加上如下*Bean *定義: ~~~ @Bean public Realm realm() { return new MyCustomRealm(); } @Bean public ShiroFilterChainDefinition shiroFilterChainDefinition() { DefaultShiroFilterChainDefinition filter = new DefaultShiroFilterChainDefinition(); filter.addPathDefinition("/secure", "authc"); filter.addPathDefinition("/**", "anon"); return filter; } ~~~ 在*ShiroFilterChainDefinition*里,我們應用*authc *過濾*/secure*路徑,又應用*anon*過濾通配符表示的其他路徑。 *authc*和*anon*都是默認為web應用提供的。其他默認的過濾器可在[這里](https://shiro.apache.org/web.html#Web-DefaultFilters)找到。 如果我們不定義*Realm*bean。*ShiroAutoConfiguration*將默認提供一個*IniRealm *實現,它會去找*src/main/resources*或者*src/main/resources/META-INF*下的*shiro.ini *文件。 如果我們不定義一個*ShiroFilterChainDefinition*bean。框架保護所有的路徑并且設置登錄URL為*login.jsp*。 我們可以改變默認的登錄URL并且添加其他默認項到我們的*application.properties*: ~~~ shiro.loginUrl = /login shiro.successUrl = /secure shiro.unauthorizedUrl = /login ~~~ 現在*authc *過濾器作用與*/secure*。該路徑的所有請求將要求身份認證。 #### 9.3.認證和授權 創建一個*ShiroSpringController*來映射以下路徑:*/index,/login, /logout* 和 */secure*。 我們實際實現上述的用戶認證在*login() *方法中。如果認證成功,用戶重定向到安全級別頁面: ~~~ Subject subject = SecurityUtils.getSubject(); if(!subject.isAuthenticated()) { UsernamePasswordToken token = new UsernamePasswordToken( cred.getUsername(), cred.getPassword(), cred.isRememberMe()); try { subject.login(token); } catch (AuthenticationException ae) { ae.printStackTrace(); attr.addFlashAttribute("error", "Invalid Credentials"); return "redirect:/login"; } } return "redirect:/secure"; ~~~ 現在來實現*secure()*,當前用戶通過*SecurityUtils.getSubject()*獲取*currentUser *。角色和用戶權限還有用戶名通過安全級別頁面傳遞: ~~~ Subject currentUser = SecurityUtils.getSubject(); String role = "", permission = ""; if(currentUser.hasRole("admin")) { role = role + "You are an Admin"; } else if(currentUser.hasRole("editor")) { role = role + "You are an Editor"; } else if(currentUser.hasRole("author")) { role = role + "You are an Author"; } if(currentUser.isPermitted("articles:compose")) { permission = permission + "You can compose an article, "; } else { permission = permission + "You are not permitted to compose an article!, "; } if(currentUser.isPermitted("articles:save")) { permission = permission + "You can save articles, "; } else { permission = permission + "\nYou can not save articles, "; } if(currentUser.isPermitted("articles:publish")) { permission = permission + "\nYou can publish articles"; } else { permission = permission + "\nYou can not publish articles"; } modelMap.addAttribute("username", currentUser.getPrincipal()); modelMap.addAttribute("permission", permission); modelMap.addAttribute("role", role); return "secure"; ~~~ 自此,我們完成了怎樣繼承Apache Shiro到Spring Boot應用。 . 同時,注意可以使用框架提供的額外[注解](https://shiro.apache.org/spring.html)來配合過濾器鏈定義來保證我們應用的安全。 ### 10.JEE整合 整合Apache Shiro到一個JEE應用可以看成一個配置web.xml文件的問題。像往常一樣, 配置會先在class路徑下找*shiro.ini*。一個詳細的配置例子在[這](https://shiro.apache.org/web.html#Web-%7B%7Bweb.xml%7D%7D)。此外,JSP標簽可以在[這](https://shiro.apache.org/web.html#Web-JSP%2FGSPTagLibrary)找到。 ### 11.結語 在本教程中,我們認識了Apache Shiro的認證與授權機制。我們也關注到怎樣定義一個自定義realm并且把它交個SecurityManager。 一如既往,完整源碼可以[在GitHub](https://github.com/eugenp/tutorials/tree/master/apache-shiro)獲取。 譯者主頁:[rebey.cn](http://rebey.cn/)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看