更新時(shí)間:2022-12-20 10:30:36 來(lái)源:動(dòng)力節(jié)點(diǎn) 瀏覽1221次
Shiro訪問(wèn)權(quán)限控制是什么?動(dòng)力節(jié)點(diǎn)小編來(lái)為大家進(jìn)行詳細(xì)的介紹。
1.什么是權(quán)限控制
白話文:控制某某用戶可以/不可以訪問(wèn)某某功能。
我們今天的Shiro訪問(wèn)權(quán)限控制,實(shí)際上就是對(duì)資源加鎖,每個(gè)鎖都有一些規(guī)則,只有對(duì)應(yīng)的鑰匙才能打開(kāi),我們根據(jù)用戶的角色,將鑰匙分配給不同用戶。
2.權(quán)限控制的方式
(1)基于過(guò)濾器進(jìn)行控制。比如我們servlet中的filter
(2)基于注解進(jìn)行控制。可以借助spring的AOP進(jìn)行控制。
(3)直接在業(yè)務(wù)代碼中判斷(不可取)
(4)頁(yè)面標(biāo)簽的權(quán)限控制——不太常用。
1.功能
認(rèn)證:即我們常說(shuō)的登錄
授權(quán):給予用戶資源權(quán)限
會(huì)話:當(dāng)前認(rèn)證用戶會(huì)話
緩存:緩存認(rèn)證權(quán)限等
2.權(quán)限控制方式:
filter方式
//設(shè)置過(guò)濾匹配路徑和判斷規(guī)則
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
filterChainDefinitionMap.put("/**", "anon");//可以匿名訪問(wèn)
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
注解方式
//在具體的方法上添加注解
@RequiresAuthentication :表示當(dāng)前Subject已經(jīng)認(rèn)證:Subject.isAuthenticated()返回true
@RequiresUse:表示當(dāng)前Subject已經(jīng)身份驗(yàn)證或者通過(guò)記住我登錄的
@RequiresGuest :表示當(dāng)前Subject沒(méi)有身份驗(yàn)證或通過(guò)記住我登錄過(guò),即是游客身份
@RequiresRoles(value={“admin”, “user”}, logical= Logical.AND)
@RequiresPermissions(value={“user:select”, “user:all”}, logical= Logical.OR)
只是用注解是不生效的,需要添加配置
/**
* 注解支持:
*/
@Bean
@ConditionalOnMissingBean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator defaultAAP = new DefaultAdvisorAutoProxyCreator();
defaultAAP.setProxyTargetClass(true);
return defaultAAP;
}?
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
標(biāo)簽(了解)
注意,此處使用的是thymeleaf做視圖界面展示,并非jsp
<!--輸出當(dāng)前用戶信息,通常為登錄帳號(hào)信息。如果存入的principal是對(duì)象,可以通過(guò)property取值-->
<span> <shiro:principal property="username"/> </span>
<!--驗(yàn)證當(dāng)前用戶是否擁有指定權(quán)限。 -->
<a shiro:hasPermission="user:select" href="#" >查看用戶列表</a><!-- 擁有權(quán)限 -->
<!--與hasPermission標(biāo)簽邏輯相反,當(dāng)前用戶沒(méi)有制定權(quán)限時(shí),驗(yàn)證通過(guò)。-->
<p shiro:lacksPermission="user:del"> 沒(méi)有權(quán)限 </p>
<!--驗(yàn)證當(dāng)前用戶是否擁有以下所有權(quán)限。-->
<p shiro:hasAllPermissions="user:view, user:add">擁有所有才能訪問(wèn)</p>
<!--驗(yàn)證當(dāng)前用戶是否擁有以下任意一個(gè)權(quán)限。-->
<p shiro:hasAnyPermissions="user:view, user:del">擁有任意一個(gè)即可訪問(wèn)</p>
<!--驗(yàn)證當(dāng)前用戶是否屬于該角色。-->
<a shiro:hasRole="role_admin" href="#">是role_admin角色</a>
<!--與hasRole標(biāo)簽邏輯相反,當(dāng)用戶不屬于該角色時(shí)驗(yàn)證通過(guò)。-->
<p shiro:lacksRole="role_admin">我沒(méi)有role_admin角色</p>
<!--驗(yàn)證當(dāng)前用戶是否屬于以下所有角色。-->
<p shiro:hasAllRoles="developer, admin"> 角色與判斷 </p>
<!--驗(yàn)證當(dāng)前用戶是否屬于以下任意一個(gè)角色。-->
<p shiro:hasAnyRoles="admin, vip, developer"> 角色或判斷 </p>
<!--驗(yàn)證當(dāng)前用戶是否為“訪客”,即未認(rèn)證(包含未記住)的用戶。-->
<p shiro:guest="">訪客 未認(rèn)證</a></p>
<!--已認(rèn)證通過(guò)的用戶。不包含已記住的用戶,這是與user標(biāo)簽的區(qū)別所在。-->
<p shiro:authenticated=""> <span shiro:principal=""></span> </p>
<!--未認(rèn)證通過(guò)用戶,與authenticated標(biāo)簽相對(duì)應(yīng)。-->
<!--與guest標(biāo)簽的區(qū)別是,該標(biāo)簽包含已記住用戶。-->
<p shiro:notAuthenticated=""> 未認(rèn)證通過(guò)用戶 </p>
1.SecurityManager
@Bean
public SecurityManager securityManager(){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
List<Realm> realms = new ArrayList<Realm>();
realms.add(customRealm());
securityManager.setRealms(realms);
securityManager.setSessionManager(sessionManager());
return securityManager;
}
2.Realm
//主要用作封裝認(rèn)證、授權(quán)信息,返回給安全管理器處理
@Bean
public CustomRealm customRealm(){
CustomRealm customRealm = new CustomRealm();
//設(shè)置密碼校驗(yàn)算法——需要和加密算法一致
customRealm.setCredentialsMatcher(credentialsMatcher());
return customRealm;
}?
@Bean
public CredentialsMatcher credentialsMatcher(){
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
hashedCredentialsMatcher.setHashAlgorithmName("md5");//散列算法:這里使用MD5算法;
// hashedCredentialsMatcher.setHashIterations(2);
return hashedCredentialsMatcher;
}
3.ShiroFilter
@Bean
public ShiroFilterFactoryBean shiroFilter2(SecurityManager securityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
shiroFilterFactoryBean.setLoginUrl("/admin/toPage");
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
//訪問(wèn)控制
filterChainDefinitionMap.put("/admin/toPage", "anon");//可以匿名訪問(wèn)
filterChainDefinitionMap.put("/admin/login", "anon");//可以匿名訪問(wèn)
filterChainDefinitionMap.put("/storage/list", "perms[user:select]");//可以匿名訪問(wèn)
// filterChainDefinitionMap.put("/", "anon");//可以匿名訪問(wèn)
filterChainDefinitionMap.put("/**", "anon");//可以匿名訪問(wèn)
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
4.SessionManager
@Bean
public SessionManager sessionManager() {
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
sessionManager.setSessionDAO(redisSessionDAO());?
//設(shè)置會(huì)話過(guò)期時(shí)間
sessionManager.setGlobalSessionTimeout(3*60*1000); //默認(rèn)半小時(shí)
sessionManager.setDeleteInvalidSessions(true); //默認(rèn)自定調(diào)用SessionDAO的delete方法刪除會(huì)話?
//設(shè)置會(huì)話定時(shí)檢查
sessionManager.setSessionValidationInterval(180000); //默認(rèn)一小時(shí)
sessionManager.setSessionValidationSchedulerEnabled(true);
return sessionManager;
}?
@Bean
public SessionDAO redisSessionDAO(){
ShiroSessionRedisDAO redisDAO = new ShiroSessionRedisDAO();
return redisDAO;
}
5.用戶新增
在controller中接收新增用戶后,交給service的saveAdmin做密碼加密后保存
public void saveAdmin(Administrator admin) {
//對(duì)密碼進(jìn)行加密處理
//1.得到明文密碼
String password = admin.getPassword();
//2.生成隨機(jī)鹽 4-8位的隨機(jī)數(shù)字
String randomSalt = RandomStringUtils.randomNumeric(4, 8);
admin.setPrivateSalt(randomSalt);
//3.md5加密 添加隨機(jī)鹽,加密次數(shù)1次(當(dāng)然,這個(gè)一次可以配置在配置文件在,此處注入讀取)
Md5Hash md5Hash = new Md5Hash(password,randomSalt,1);
String hashPwd = md5Hash.toString();
admin.setPassword(hashPwd);
userMapper.insert(admin);
}
6.用戶登錄
認(rèn)證
@Controller
@RequestMapping("/admin")
public class LoginController {
@PostMapping("/login")
public String login(
@RequestParam("username") String username,
@RequestParam("password") String password,Model map){
try {
Subject subject = SecurityUtils.getSubject();
//處理登錄的用戶名密碼token
UsernamePasswordToken token =
new UsernamePasswordToken(username, password);
//登錄(開(kāi)始認(rèn)證)
subject.login(token);
return "redirect:/admin/main";
}catch (UnknownAccountException ukactException){
//用戶不存在異常
ukactException.printStackTrace();
map.addAttribute("err_msg","用戶不存在");
return "login";
}catch (IncorrectCredentialsException credentialExctption){
credentialExctption.printStackTrace();
map.addAttribute("err_msg","密碼錯(cuò)誤");
return "login";
}catch (Exception e){
e.printStackTrace();
map.addAttribute("err_msg","服務(wù)器錯(cuò)誤,請(qǐng)重試");
return "login";
}
}
}
1.thymeleaf中使用shiro標(biāo)簽的支持
依賴坐標(biāo):
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.0.0</version>
</dependency>
配置支持:
@Bean
public ShiroDialect shiroDialect(){
return new ShiroDialect();
}
2.request判斷ajax請(qǐng)求
//通過(guò)頭X-Requested-With=XMLHttpRequest來(lái)判斷
request.getHeader("X-Requested-With");
0基礎(chǔ) 0學(xué)費(fèi) 15天面授
有基礎(chǔ) 直達(dá)就業(yè)
業(yè)余時(shí)間 高薪轉(zhuǎn)行
工作1~3年,加薪神器
工作3~5年,晉升架構(gòu)
提交申請(qǐng)后,顧問(wèn)老師會(huì)電話與您溝通安排學(xué)習(xí)
初級(jí) 202925
初級(jí) 203221
初級(jí) 202629
初級(jí) 203743