Shiro登錄認證


一、登錄認證

  即在應用中誰能證明他就是他本人。一般提供如他們的身份ID 一些標識信息來表明他就是他本人,如提供身份證,用戶名/密碼來證明。

  在 shiro 中,用戶需要提供principals (身份)和credentials(證明)給shiro,從而應用能驗證用戶身份。

二、Shiro登錄認證基本概念

1,principals

  身份,即主體的標識屬性,可以是任何東西,如用戶名、郵箱等,唯一即可。

  一個主體可以有多個principals,但只有一個Primary principals,一般是用戶名/密碼/手機號。

2, credentials

  證明/憑證,即只有主體知道的安全值,如密碼/數字證書等。

  最常見的principals和credentials組合就是用戶名/密碼了。接下來先進行一個基本的身份認證。

三、Shiro登錄認證流程

1、首先調用Subject.login(token)進行登錄,其會自動委托給Security Manager,調用之前必須通過SecurityUtils. setSecurityManager()設置;

2、SecurityManager負責真正的身份驗證邏輯;它會委托給Authenticator進行身份驗證;

3、Authenticator才是真正的身份驗證者,Shiro API中核心的身份認證入口點,此處可以自定義插入自己的實現;

4、Authenticator可能會委托給相應的AuthenticationStrategy進行多Realm身份驗證,默認ModularRealmAuthenticator會調用AuthenticationStrategy進行多Realm身份驗證;

5、Authenticator 會把相應的token 傳入Realm,從Realm 獲取身份驗證信息,如果沒有返回/拋出異常表示身份驗證失敗了。此處可以配置多個Realm,將按照相應的順序及策略進行訪問。

 四、Shiro在SpringBoot中Demo

Config.java

 1 package io.guangsoft.shiro.config;  2 
 3 import java.util.LinkedHashMap;  4 import java.util.Map;  5 
 6 import io.guangsoft.shiro.realm.Realm;  7 import org.apache.shiro.authc.credential.HashedCredentialsMatcher;  8 import org.apache.shiro.mgt.RememberMeManager;  9 import org.apache.shiro.mgt.SecurityManager; 10 import org.apache.shiro.spring.web.ShiroFilterFactoryBean; 11 import org.apache.shiro.web.mgt.CookieRememberMeManager; 12 import org.apache.shiro.web.mgt.DefaultWebSecurityManager; 13 import org.apache.shiro.web.servlet.SimpleCookie; 14 import org.springframework.context.annotation.Bean; 15 import org.springframework.context.annotation.Configuration; 16 
17 @Configuration 18 public class Config { 19 
20  @Bean 21     public Realm realmManager() { 22         // 加密相關
23         HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(); 24         // 散列算法
25         hashedCredentialsMatcher.setHashAlgorithmName("md5"); 26         // 散列次數
27         hashedCredentialsMatcher.setHashIterations(2); 28         Realm realm = new Realm(); 29  realm.setCredentialsMatcher(hashedCredentialsMatcher); 30         return realm; 31  } 32 
33  @Bean 34     public RememberMeManager rememberMeManager() { 35         CookieRememberMeManager rememberMeManager = new CookieRememberMeManager(); 36         //注入自定義cookie(主要是設置壽命, 默認的一年太長)
37         SimpleCookie simpleCookie = new SimpleCookie(); 38         simpleCookie.setHttpOnly(true); 39         //設置RememberMe的cookie有效期為7天
40         simpleCookie.setMaxAge(604800); 41  rememberMeManager.setCookie(simpleCookie); 42         return rememberMeManager; 43  } 44 
45  @Bean 46     public SecurityManager securityManager() { 47         DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); 48  securityManager.setRealm(realmManager()); 49  securityManager.setRememberMeManager(rememberMeManager()); 50         return securityManager; 51  } 52 
53  @Bean 54     public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) { 55         ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); 56  shiroFilterFactoryBean.setSecurityManager(securityManager); 57         //當用戶未登錄則跳轉到登錄路徑
58         shiroFilterFactoryBean.setLoginUrl("/login"); 59         //登錄成功后要跳轉的鏈接,表單登錄方式有效
60         shiroFilterFactoryBean.setSuccessUrl("/index"); 61         //未授權界面,指定沒有權限操作時跳轉頁面
62         shiroFilterFactoryBean.setUnauthorizedUrl("/warning"); 63         //配置不會被過濾的鏈接順序判斷,過慮器鏈定義,從上向下順序執行,一般將/**放在最下邊
64         Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>(); 65         //對靜態資源設置匿名訪問,anon:所有url都可以匿名訪問
66         filterChainDefinitionMap.put("/assets/**", "anon"); 67         //放開登錄接口,允許進行登錄操作
68         filterChainDefinitionMap.put("/shiro/login", "anon"); 69         //配置退出過濾器,其中的具體的退出代碼Shiro已經替我們實現了
70         filterChainDefinitionMap.put("/shiro/logout", "logout"); 71         //authc:所有url都必須認證通過才可以訪問
72         filterChainDefinitionMap.put("/**", "authc"); 73  shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); 74         return shiroFilterFactoryBean; 75  } 76 
77 }

Realm.java

 1 package io.guangsoft.shiro.realm;  2 
 3 import org.apache.shiro.authc.AuthenticationException;  4 import org.apache.shiro.authc.AuthenticationInfo;  5 import org.apache.shiro.authc.AuthenticationToken;  6 import org.apache.shiro.authc.SimpleAuthenticationInfo;  7 import org.apache.shiro.authz.AuthorizationInfo;  8 import org.apache.shiro.authz.SimpleAuthorizationInfo;  9 import org.apache.shiro.realm.AuthorizingRealm; 10 import org.apache.shiro.subject.PrincipalCollection; 11 import org.apache.shiro.util.ByteSource; 12 
13 import java.util.ArrayList; 14 import java.util.List; 15 
16 public class Realm extends AuthorizingRealm { 17 
18         //認證,模擬從數據庫查詢出密碼
19  @Override 20    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { 21         String userName = (String) token.getPrincipal(); 22         String password = "4d521acb9b8b3b4fa082ab16b3bd363a"; 23         String salt = "guanghe"; 24         return new SimpleAuthenticationInfo(userName, password, ByteSource.Util.bytes(salt), this.getName()); 25  }
26 }

ShiroController.java

 1 package io.guangsoft.shiro.controller;  2 
 3 import com.alibaba.fastjson.JSONObject;  4 import org.apache.shiro.SecurityUtils;  5 import org.apache.shiro.authc.*;  6 import org.apache.shiro.subject.Subject;  7 import org.springframework.web.bind.annotation.RequestMapping;  8 import org.springframework.web.bind.annotation.RestController;  9 
10 @RestController 11 @RequestMapping("shiro") 12 public class ShiroController { 13 
14     @RequestMapping(value = "login") 15     public String login(String username, String password, Boolean rememberMe) { 16         Subject subject = SecurityUtils.getSubject(); 17         UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username, password); 18  usernamePasswordToken.setRememberMe(rememberMe); 19         String msg = null; 20         try { 21  subject.login(usernamePasswordToken); 22             msg = "身份認證成功!"; 23         } catch (UnknownAccountException e) { 24  e.printStackTrace(); 25             msg = "賬號不存在!"; 26         } catch (LockedAccountException e) { 27  e.printStackTrace(); 28             msg = "賬號被鎖定!"; 29         } catch (DisabledAccountException e) { 30  e.printStackTrace(); 31             msg = "賬號被禁用!"; 32         } catch (IncorrectCredentialsException e) { 33  e.printStackTrace(); 34             msg = "憑證/密碼錯誤!"; 35         } catch (ExpiredCredentialsException e) { 36  e.printStackTrace(); 37             msg = "憑證/密碼過期!"; 38         } catch (ExcessiveAttemptsException e) { 39  e.printStackTrace(); 40             msg = "登錄失敗次數過多!"; 41  } 42         JSONObject result = new JSONObject(); 43         if(subject.isAuthenticated()) { 44             result.put("code", 0); 45         } else { 46             result.put("code", -1); 47  } 48         result.put("msg", msg); 49         return result.toString(); 50  } 51 }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM