文章目錄
Shiro分爲認證和授權
認證中抽象出來的對象
Subject:主體
訪問系統的用戶,主體可以是用戶,程序等。進行認證的都成爲主體。
Principal:身份信息
是主體(subject)進行身份認證的標識,標識必須具有唯一性,如用戶名、手機號、郵箱地址等,一個主體可以
有多個身份,但是必須有一個主身份(Primary Principal),比如手機號登錄,或者賬戶登錄。
Credential:憑證信息
是隻有主體自己知道的安全信息,如密碼、證書等。
授權中抽象出來的對象
授權可簡單理解爲who對what(which)進行How操作:
Who,即主體(Subject)
主體需要訪問系統中的資源。
What,即資源(Resource)
如系統菜單、頁面、按鈕、類方法、系統商品信息等。資源包括資源類型和資源實例,比如商品信息爲資源類型,類型爲t01的商品爲資源實例,編號爲001的商品信息也屬於資源實例。
How,權限/許可(Permission)
規定了主體對資源的操作許可,權限離開資源沒有意義,如用戶查詢權限、用戶添加權限、某個類方法的調用權限、編號爲001用戶的修改權限等,通過權限可知主體對哪些資源都有哪些操作
許可。
權限分爲粗顆粒和細顆粒,粗顆粒權限是指對資源類型的權限,細顆粒權限是對資源實例的權限
shiro架構圖
權限模型
shiro的授權
subject.isAuthenticated() //登錄是否成功
subject.hasRole("admin") //驗證是否有admin角色
subject.hasAllRoles(Arrays.asList("admin","super")) //驗證是否包含所有角色
subject.hasRoles(Arrays.asList("admin","super")) //驗證是否有某一個角色
subject.isAuthenticated() //驗證是否登錄成功
subject.isPermitted("user:delete") //驗證用戶是否有該權限
web頁面shiro標籤
<shiro:authenticated></shiro:authenticated> //已經認證
<shiro:notAuthenticated></shiro:notAuthenticated> //未認證
<shiro:principal></shiro:principal> //獲取主身份信息
<shiro:hasRole name="admin"></shiro:hasRole> //判斷是否有該角色
<shiro:hasAnyRoles name="admin,super"></shiro:hasAnyRoles> //判斷是否有某一個角色(有一個就可執行)
<shiro:hasPermission name="banner:delete"></shiro:hasPermission> //判斷是否有該權限
認證和授權流程圖
SpringBoot整合Shiro
引入依賴
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-web-starter</artifactId>
<version>1.4.1</version>
</dependency>
創建shiro過濾器
package cn.czboy.shiro;
import org.apache.shiro.cache.MemoryConstrainedCacheManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
@Configuration
public class ShiroFilter {
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
System.out.println("===========shiroFilter");
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
HashMap<String,String> map = new HashMap<>();
map.put("/subject/**","anon");
map.put("/login.jsp","anon");
map.put("/index.jsp","anon");
map.put("/**","authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
shiroFilterFactoryBean.setLoginUrl("/login.jsp");//設置攔截後跳轉的網頁
shiroFilterFactoryBean.setSecurityManager(securityManager);
return shiroFilterFactoryBean;
}
@Bean
public DefaultWebSecurityManager securityManager(MyRealm myRealm) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
MemoryConstrainedCacheManager cache = new MemoryConstrainedCacheManager();
securityManager.setCacheManager(cache);
securityManager.setRealm(myRealm);
return securityManager;
}
@Bean
public MyRealm myRealm() {
MyRealm myRealm = new MyRealm();
return myRealm;
}
}
創建自定義Realm
package cn.czboy.shiro;
import cn.czboy.entity.Role;
import cn.czboy.entity.Subject;
import cn.czboy.mapper.SubjectDao;
import cn.czboy.utils.SpringContextUtil;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
public class MyRealm extends AuthorizingRealm {
/**授權*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
String username = (String)principalCollection.getPrimaryPrincipal();
SubjectDao subjectDao = (SubjectDao)SpringContextUtil.getBean(SubjectDao.class);
//根據主體獲取角色
List<Role> roles = subjectDao.findByRole(username);
HashSet<String> set = new HashSet<>();
ArrayList<String> arrayList = new ArrayList<>();
SimpleAuthorizationInfo authorizationInfo = null;
if(primaryPrincipal.equals(admin.getUsername())){
authorizationInfo = new SimpleAuthorizationInfo();
for(RoleDto role:roles){
arrayList.add(role.getRoleName());
String id = role.getId();
//根據角色查權限
List<String> permissionss = adminService.findByPermission(id);
for(String key:permissionss){
set.add(key);
}
}
authorizationInfo.addStringPermissions(set);//權限賦值
authorizationInfo.addRoles(arrayList);//角色賦值
}
return authorizationInfo;
}
/**認證*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
String username = (String)authenticationToken.getPrincipal();
String password = new String((char[]) authenticationToken.getCredentials());
SubjectDao subjectDao = (SubjectDao)SpringContextUtil.getBean(SubjectDao.class);
Subject subject = subjectDao.findByUserName(username);
AuthenticationInfo authenticationInfo = null;
if (subject == null) {
throw new UnknownAccountException("賬戶不存在!");
}
if (!subject.getUsername().equals(username)) {
throw new UnknownAccountException("用戶名錯誤!");
}
if (!subject.getPassword().equals(password)) {
throw new IncorrectCredentialsException("密碼錯誤!");
}
authenticationInfo = new SimpleAuthenticationInfo(subject.getUsername(), subject.getPassword(), this.getName());
System.out.println("================="+subject);
return authenticationInfo;
}
}
SubjectController
package cn.czboy.controller;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.subject.Subject;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/subject")
public class SubjectController {
/**用戶登陸*/
@RequestMapping("/login")
public String login(String username,String password) {
System.out.println("========="+username);
System.out.println("========="+password);
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
try {
subject.login(token);
return "yes";
} catch (UnknownAccountException e) {
System.out.println(e.getMessage());
return "no";
} catch (IncorrectCredentialsException e) {
System.out.println(e.getMessage());
return "no";
}
}
}