<!doctype html>
Shiro | Spring Security |
---|---|
簡單,靈活 | 複雜,笨重 |
可脫離Spring | 不可脫離Spring |
粒度較粗 | 粒度更細 |
主要分爲兩大塊 Subject
和Security Manager
html
能夠理解爲當前的操做用戶java
是Shiro的核心,她管理着其餘組件的實例。它包含下面這些組件node
Authenticator(認證)git
咱們應用的認證器,管理登陸,登出github
Authorizer(受權)web
咱們應用的受權器,主要賦予Subject(當前的操做用戶)有哪些權限算法
Session Managerspring
Shiro本身實現的一套管理機制,能夠在不借用任何web容器下使用session,下面的Session Dao是提供了一些Session的操做,主要有增刪改查sql
Cache Manager
緩存管理器,主要用於緩存角色數據和權限數據
Realms
充當了 Shiro 與應用安全數據間的「橋樑」或者「鏈接器」,Shiro經過它來從數據庫中獲取認證數據、角色數據和權限數據。
Cryptography(加密)
Shiro提供的加密工具,能夠使用她很是快捷,方便的來作數據加密
更多信息查看 官方架構文檔
更多信息請查看 認證官方文檔
更多信息請查看 受權官方文檔
更多信息請查看 Realm官方文檔
從配置文件中獲取用戶、角色和權限數據
x
[main]
# 提供了對根對象 securityManager 及其依賴的配置
securityManager=org.apache.shiro.mgt.DefaultSecurityManager
[users]
# 提供了對用戶/密碼及其角色的配置
# username=password,role1,role2
admin=123456,admin
[roles]
# 提供了角色及權限之間關係的配置
# role=permission1,permission2
admin=c,r,u,d
[urls]
# 用於 web,提供了對 web url 攔截相關的配置,
# url=攔截器[參數],攔截器
/index.html=anon
/admin/=authc, roles[admin], perms["permission1"]
SecurityManager中注入 org.apache.shiro.realm.text.IniRealm
類並指定配置文件路徑便可
從數據庫中獲取用戶、角色和權限數據。可是該Realm有一些默認的查詢語句,而且指定了表名和字段名,雖然能夠修改他默認的sql語句,可是不夠方便。所以仍是自定義Realm方便一些。
SecurityManager中注入 org.apache.shiro.realm.jdbc.JdbcRealm
類並建立對應的表和字段便可
建立類繼承AuthorizingRealm
並實現其方法,以後在SecurityManager中注入該類便可。
實現方法以下(該實現方法採用MybatisPlus爲持久層框架)
xxxxxxxxxx
/ 受權 */
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
User user = (User)principalCollection.getPrimaryPrincipal();
List<Role> roleList = userService.selectAllRole(user);
List<Permission> permissionList = userService.selectAllPermissionByUid(user);
if(!roleList.isEmpty()){
roleList.forEach(e->{
authorizationInfo.addRole(e.getRid().toString());
});
}
if(!permissionList.isEmpty()){
permissionList.forEach(e->{
authorizationInfo.addStringPermission(e.getPermissionCode());
});
}
return authorizationInfo;
}
/** 認證 */
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
String username = (String)authenticationToken.getPrincipal();
User user = userService.selectOne(new EntityWrapper<User>().eq("username", username));
if(Objects.isNull(user)){
return null;
}
if(user.getStatus() == 2){
throw new LockedAccountException();
}
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user,user.getPassword(),this.getName());
return authenticationInfo;
}
這是Shiro的一個加密工具類,能夠設置加密算法和加密算法的加密次數
hashAlgorithm 該屬性指定加密的算法
hashIterations 該屬性指定加密算法的加密次數
直接在Realm中配置HashedCredentialsMatcher並設置加密算法和次數便可
Springboot中配置加密以下
xxxxxxxxxx
(name = "hashedCredentialsMatcher")
public HashedCredentialsMatcher hashedCredentialsMatcher() {
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
hashedCredentialsMatcher.setHashAlgorithmName("MD5");// 散列算法:這裏使用MD5算法;
hashedCredentialsMatcher.setHashIterations(2);// 散列的次數,好比散列兩次,至關於md5(md5(""));
return hashedCredentialsMatcher;
}
public ShiroRealm shiroRealm( ("hashedCredentialsMatcher") HashedCredentialsMatcher matcher){
ShiroRealm shiroRealm = new ShiroRealm();
// 設置密碼憑證匹配器
shiroRealm.setCredentialsMatcher(matcher);
return shiroRealm;
}
加鹽是爲了讓密碼更加難以識破,通常都是生成一個隨機數來和密碼一塊兒使用。
直接在Realm認證方法中添加一個參數便可
xxxxxxxxxx
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user,user.getPassword(),ByteSource.Util.bytes(user.getSalt()),this.getName());
下面代碼爲生成隨機鹽值和經過鹽加密後的密碼
xxxxxxxxxx
//隨機數生成器
RandomNumberGenerator randomNumberGenerator = new SecureRandomNumberGenerator();
String salt = randomNumberGenerator.nextBytes().toHex();
String password = new SimpleHash("MD5",user.getPassword(),ByteSource.Util.bytes(salt),2).toHex();
認證過濾器
org.apache.shiro.web.filter.authc.AuthenticatingFilter
過濾器 | 說明 |
---|---|
anon | 不須要認證,直接能夠訪問 |
authBasic | httpBasic認證 |
authc | 須要認證才能訪問 |
user | 須要當前存在用戶才能訪問 |
logout | 登出 |
受權過濾器
org.apache.shiro.web.filter.authz.AuthorizationFilter
過濾器 | 說明 |
---|---|
perms | 具有相關的權限才能夠訪問 |
roles | 具有相關的角色才能夠訪問 |
ssl | 安全協議,也就是https |
port | 訪問指定的端口才能夠訪問 |
更多過濾器查看 過濾器官方文檔
在ShiroFilterFactoryBean中設置屬性 filterChainDefinitionMap
便可,注意他是鏈式過濾的,就是說是安裝從上到下進行過濾的。下面給出一個Springboot的例子
xxxxxxxxxx
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
//攔截器
Map<String,String> filterChainDefinitionMap = new LinkedHashMap<>();
filterChainDefinitionMap.put("/authc","anon");
filterChainDefinitionMap.put("/login","anon");
// 過濾swagger
filterChainDefinitionMap.put("/swagger-ui.html", "anon");
filterChainDefinitionMap.put("/swagger-resources/", "anon");
filterChainDefinitionMap.put("/v2/api-docs/", "anon");
filterChainDefinitionMap.put("/webjars/springfox-swagger-ui/", "anon");
//過濾druid
filterChainDefinitionMap.put("/druid/","anon");
//配置退出 過濾器,其中的具體的退出代碼Shiro已經替咱們實現了
filterChainDefinitionMap.put("/logout", "logout");
//過濾鏈定義,從上向下順序執行,通常將/放在最爲下邊
//authc:全部url都必須認證經過才能夠訪問; anon:全部url都均可以匿名訪問
filterChainDefinitionMap.put("/", "authc");
// 若是不設置默認會自動尋找Web工程根目錄下的"/login.jsp"頁面
shiroFilterFactoryBean.setLoginUrl("/authc");
// 登陸成功後要跳轉的連接
//shiroFilterFactoryBean.setSuccessUrl("/index");
//未受權界面;用戶訪問未對其受權的資源時,所顯示的鏈接 可是使用註解的話這段不起做用,須要使用異常處理器重定向頁面
shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
須要認證攔截就繼承 org.apache.shiro.web.filter.authc.AuthenticatingFilter
類,重寫父類中的方法。
須要受權攔截就繼承 org.apache.shiro.web.filter.authz.AuthorizationFilter
類,重寫父類中的方法。
寫好攔截器後須要注入到ShiroFilter中便可,更多過濾器信息請直接查看源碼進行了解
Shiro本身實現了一套Session管理體系,他能夠使咱們在不介入Web容器和Servlet下使用Session。
更多信息查看 會話管理官方文檔
Shiro提供的一個Session管理器
提供Session的增刪改查操做
org.apache.shiro.session.mgt.eis.AbstractSessionDAO
並重寫其方法,主要包括基本增刪改查以及獲取全部活動的Sessionorg.apache.shiro.web.session.mgt.DefaultWebSessionManager
重寫retrieveSession
方法,能夠設置爲先從Request中獲取,取不到則從Redis中獲取。這樣能夠減輕Redis的壓力CacheManager,主要用來緩存角色數據和權限數據,這樣就能夠不用每次受權的時候都要去數據庫查詢角色和權限信息。主要是經過CacheManager和Cache這兩個接口來管理Cache
更多緩存信息請查看 緩存官方文檔
org.apache.shiro.cache.Cache<K,V>
接口並實現相應的方法org.apache.shiro.cache.CacheManager
接口並實現相應的方法org.apache.shiro.web.servlet.SimpleCookie
對象,並設置Cookie名稱和過時時間org.apache.shiro.web.mgt.CookieRememberMeManager
對象,並設置Cookie爲SimpleCookie對象rememberMeManager
中org.apache.shiro.authc.UsernamePasswordToken
對象中設置rememberMe
屬性,這是一個boolean值