摘要:當(dāng)前可以是身份,不需要經(jīng)過(guò)認(rèn)證或者在原先的中存在記錄。當(dāng)前必須擁有所有指定的角色時(shí),才能訪問(wèn)被該注解標(biāo)注的方法。
關(guān)于 Apache Shiro 概念基本都粘自官網(wǎng) http://shiro.apache.org/Shiro 簡(jiǎn)介
詳細(xì)中文博客 http://wiki.jikexueyuan.com/p...
與SpringBoot整合 https://segmentfault.com/a/11...
Apache Shiro是一個(gè)功能強(qiáng)大且靈活的開(kāi)源安全框架,可以清晰地處理身份驗(yàn)證,授權(quán),企業(yè)會(huì)話管理和加密。
以下是Apache Shiro可以做的一些事情:
驗(yàn)證用戶以驗(yàn)證其身份
為用戶執(zhí)行訪問(wèn)控制
在任何環(huán)境中使用Session API,即使沒(méi)有Web容器或EJB容器也是如此。
......
功能簡(jiǎn)介Authentication:身份認(rèn)證/登錄,驗(yàn)證用戶是不是擁有相應(yīng)的身份;
Authorization:授權(quán),即權(quán)限驗(yàn)證,驗(yàn)證某個(gè)已認(rèn)證的用戶是否擁有某個(gè)權(quán)限;即判斷用戶是否能進(jìn)行什么操作,如:驗(yàn)證某個(gè)用戶是否擁有某個(gè)角色。或者細(xì)粒度的驗(yàn)證某個(gè)用戶對(duì)某個(gè)資源是否具有某個(gè)權(quán)限;
Session Manager:會(huì)話管理,即用戶登錄后就是一次會(huì)話,在沒(méi)有退出之前,它的所有信息都在會(huì)話中;會(huì)話可以是普通 JavaSE 環(huán)境,也可以是 Web 環(huán)境的;
Cryptography:加密,保護(hù)數(shù)據(jù)的安全性,如密碼加密存儲(chǔ)到數(shù)據(jù)庫(kù),而不是明文存儲(chǔ);
Web Support:Web 支持,可以非常容易的集成到Web 環(huán)境;
Caching:緩存,比如用戶登錄后,其用戶信息、擁有的角色/權(quán)限不必每次去查,這樣可以提高效率;
Concurrency:Shiro 支持多線程應(yīng)用的并發(fā)驗(yàn)證,即如在一個(gè)線程中開(kāi)啟另一個(gè)線程,能
把權(quán)限自動(dòng)傳播過(guò)去;
Testing:提供測(cè)試支持;
Run As:允許一個(gè)用戶假裝為另一個(gè)用戶(如果他們?cè)试S)的身份進(jìn)行訪問(wèn);
Remember Me:記住我,這個(gè)是非常常見(jiàn)的功能,即一次登錄后,下次再來(lái)的話不用登錄了
Shiro 詳細(xì)的架構(gòu)可以參考官方文檔:http://shiro.apache.org/archi...
Shiro web工程搭建 1.Maven 架包依賴(lài)緩存架包先用 ehcache
2.ehcache 緩存xml文件配置org.apache.shiro shiro-all 1.3.2 net.sf.ehcache ehcache 2.10.6
3.web.xml中shiro攔截器配置
4.spring文件配置 4.1基本配置shiroFilter org.springframework.web.filter.DelegatingFilterProxy targetFilterLifecycle true shiroFilter /*
4.2攔截規(guī)則附解/admin/userlist*=roles[user] /admin/adduser*=roles[user,admin] /admin/editRPRelation*=roles[admin],perms[user:insert,user:update,user:select,user:delete] /admin/editURRelation*=perms[user:select] /admin/**=authc /**=anon
攔截器 shiroFilter 的基本數(shù)據(jù)
securityManager:這個(gè)屬性是必須的
loginUrl:表示登錄成功后跳轉(zhuǎn)的頁(yè)面,不是必須的屬性,不輸入地址的話會(huì)自動(dòng)尋找項(xiàng)目web項(xiàng)目的根目錄下的”/login.jsp”頁(yè)面
successUrl:登錄成功默認(rèn)跳轉(zhuǎn)頁(yè)面,不配置則跳轉(zhuǎn)至”/”
unauthorizedUrl:沒(méi)有權(quán)限默認(rèn)跳轉(zhuǎn)的頁(yè)面
filterChainDefinitions:指定過(guò)濾規(guī)則
關(guān)于過(guò)濾器可以參考shiro提供的枚舉類(lèi) org.apache.shiro.web.filter.mgt.DefaultFilter
url 模式使用 Ant 風(fēng)格模式
Ant 路徑通配符支持?、、,注意通配符匹配不包括目錄分隔符 “/”:
?:匹配一個(gè)字符,如”/admin?” 將匹配 / admin1,但不匹配 / admin 或 / admin2;
:匹配零個(gè)或多個(gè)字符串,如 / admin * 將匹配 / admin、/admin123,但不匹配 / admin/1;
:匹配路徑中的零個(gè)或多個(gè)路徑,如 / admin/ 將匹配 / admin/a 或 / admin/a/b。
public class MyShiroRealm extends AuthorizingRealm { @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { System.out.println("********************* 進(jìn)行登錄認(rèn)證 *********************"); String username = (String) authenticationToken.getPrincipal(); //獲取提交的用戶名 User user = userRepository.findByUsername(username); if (user == null) throw new UnknownAccountException("用戶不存在, 請(qǐng)先注冊(cè)然后再來(lái)登錄"); if (user.getState() == 1) throw new LockedAccountException("該用戶已經(jīng)被管理員禁用, 請(qǐng)換個(gè)賬號(hào)登錄"); //接下來(lái)進(jìn)行密碼的比對(duì)邏輯 //參數(shù) principal 作為下面授權(quán)部分參數(shù)集合里面的一部分 //參數(shù) credentials 作為后面與token里面密碼比對(duì)基礎(chǔ) //返回值 info 作為下面自定義密碼匹類(lèi)里面比對(duì)方法的參數(shù) SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, user.getPassword(), getName()); return info; } @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { System.out.println("********************* 進(jìn)行授權(quán)認(rèn)證 *********************"); User user = (User) principalCollection.asList().get(0); //得到該用戶的所有角色和權(quán)限 Set6.自定義密碼匹對(duì)方案roles = new HashSet<>(); Set permissions = new HashSet<>(); user.getRoles().forEach(role -> { roles.add(role.getRoleName()); role.getPermissions().forEach(permission -> { permissions.add(permission.getPermissionName()); }); }); SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); info.setRoles(roles); info.setStringPermissions(permissions); return info; } @Autowired private UserRepository userRepository; }
前端密碼加密規(guī)則:ciphertext_pwd = AES.encrypt(MD5(password))
后端解密密碼規(guī)則:md5_password = AES.desEncrypt(ciphertext_pwd)
后端匹對(duì)密碼規(guī)則:(md5_password + 用戶名做鹽值) 進(jìn)行 1024 次 MD5 轉(zhuǎn)換,然后與數(shù)據(jù)庫(kù)取出密碼做比對(duì)
public class MyCredentialsMatcher implements CredentialsMatcher { @Override public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) { String tokenCredentials = new String((char[])token.getCredentials()); //前端傳過(guò)來(lái)的密碼 String accountCredentials = (String) info.getCredentials(); //數(shù)據(jù)庫(kù)查詢到的密碼 //首先對(duì)前端傳過(guò)來(lái)的密碼進(jìn)行AES解密 -> 清空 session 里面的key Session session = SecurityUtils.getSubject().getSession(); String key = (String) session.getAttribute("AESKey"); try { tokenCredentials = AesEncryptUtil.desEncrypt(tokenCredentials, key, key); } catch (Exception e) { throw new IncorrectCredentialsException("可能受到重放攻擊, AES 解密失敗"); } session.removeAttribute("AESKey"); //加密方式 待加密數(shù)據(jù) 加密鹽值 加密次數(shù) SimpleHash simpleHash = new SimpleHash("MD5", tokenCredentials, token.getPrincipal(), 1024); tokenCredentials = simpleHash.toString(); return accountCredentials.equals(tokenCredentials); } }7.登錄和注冊(cè)接口的調(diào)用
@Service("userService") public class UserServiceImpl implements UserService { @Override public void registerUser(User user) { if (userRepository.existsByUsername(user.getUsername())) { throw new RuntimeException("用戶名已經(jīng)被注冊(cè), 請(qǐng)換個(gè)用戶名"); } user.setState((byte) 0); //密碼進(jìn)行加密 SimpleHash simpleHash = new SimpleHash("MD5", user.getPassword(), user.getUsername(), 1024); user.setPassword(simpleHash.toString()); userRepository.save(user); } @Override public void login(User user) { Subject currentUser = SecurityUtils.getSubject(); if (currentUser.isAuthenticated() == false) { //沒(méi)有登錄過(guò)需要進(jìn)行登錄驗(yàn)證 UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(), user.getPassword(), false); currentUser.login(token); } } @Autowired private UserRepository userRepository; }8.多角色/權(quán)限匹對(duì)規(guī)則
從上面我們可以看到url地址規(guī)則匹配可以配置多角色和多權(quán)限,當(dāng)對(duì)應(yīng)多個(gè)角色和權(quán)限時(shí)中間用 “,” 隔開(kāi)。
以對(duì)應(yīng)多角色為例
/admin/userlist*=roles[user] /admin/adduser*=roles[user,admin]
當(dāng)訪問(wèn)第二個(gè) /admin/adduser* 時(shí)需要同時(shí)擁有 user 和 admin 角色,但是有時(shí)我們需要他們之間是或者的關(guān)系,這個(gè)時(shí)候我們就需要自定義對(duì)應(yīng)的過(guò)濾器。
以自定角色過(guò)濾器為例
... /admin/userlist*=roles[user] /admin/adduser*=roles[user,admin] ...
public class MyRolesAuthorizationFilter extends AuthorizationFilter { public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException { Subject subject = this.getSubject(request, response); String[] rolesArray = (String[])((String[])mappedValue); if (rolesArray != null && rolesArray.length != 0) { for (String role : rolesArray) { if (subject.hasRole(role)) return true; } } return false; } }
啟動(dòng)web項(xiàng)目看下自定義過(guò)濾器有沒(méi)有加進(jìn)去
9.shiro注解實(shí)現(xiàn)權(quán)限控制在有些方法多,但是權(quán)限分的細(xì)的地方用注解要比用配置的方案來(lái)的方便
使用注解首先要在spring-mvc.xml配置文件中加入以下配置
在spring.xml配置文件對(duì)于過(guò)濾器的配置就簡(jiǎn)單多了
沒(méi)有那些繁雜的配置規(guī)則和跳轉(zhuǎn)頁(yè)面
5個(gè)權(quán)限注解
RequiresAuthentication:當(dāng)前Subject必須在當(dāng)前session中已經(jīng)過(guò)認(rèn)證。
RequiresGuest:當(dāng)前Subject可以是“gust”身份,不需要經(jīng)過(guò)認(rèn)證或者在原先的session中存在記錄。
RequiresPermissions:當(dāng)前Subject需要擁有某些特定的權(quán)限時(shí),才能執(zhí)行被該注解標(biāo)注的方法。
RequiresRoles:當(dāng)前Subject必須擁有所有指定的角色時(shí),才能訪問(wèn)被該注解標(biāo)注的方法。
RequiresUser:當(dāng)前Subject必須是應(yīng)用的用戶,才能訪問(wèn)或調(diào)用被該注解標(biāo)注的類(lèi),實(shí)例,方法。
上面所有要求的權(quán)限和認(rèn)證沒(méi)有時(shí)就會(huì)拋出對(duì)應(yīng)的異常,只需在SpringMVC中寫(xiě)好對(duì)應(yīng)的異常截獲方法即可
示例
//表示需要認(rèn)證 @RequiresAuthentication //表示在需要認(rèn)證的基礎(chǔ)上要同時(shí)擁有 user 和 admin 角色 @RequiresRoles(value = {"user", "admin"}) //同上 @RequiresRoles(value = {"user", "admin"}, logical = Logical.AND) //表示在需要認(rèn)證的基礎(chǔ)上擁有 user 或 admin 角色 @RequiresRoles(value = {"user", "admin"}, logical = Logical.OR)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/73694.html
摘要:細(xì)粒度權(quán)限管理就是數(shù)據(jù)級(jí)別的權(quán)限管理。張三只能查看行政部的用戶信息,李四只能查看開(kāi)發(fā)部門(mén)的用戶信息。比如通過(guò)的攔截器實(shí)現(xiàn)授權(quán)。 前言 本文主要講解的知識(shí)點(diǎn)有以下: 權(quán)限管理的基礎(chǔ)知識(shí) 模型 粗粒度和細(xì)粒度的概念 回顧URL攔截的實(shí)現(xiàn) Shiro的介紹與簡(jiǎn)單入門(mén) 一、Shiro基礎(chǔ)知識(shí) 在學(xué)習(xí)Shiro這個(gè)框架之前,首先我們要先了解Shiro需要的基礎(chǔ)知識(shí):權(quán)限管理 1.1什...
摘要:安全框架是目前為止作為登錄注冊(cè)最常用的框架,因?yàn)樗值膹?qiáng)大簡(jiǎn)單,提供了認(rèn)證授權(quán)加密和會(huì)話管理等功能。本質(zhì)上是一個(gè)特定安全的。當(dāng)配置時(shí),必須指定至少一個(gè)用來(lái)進(jìn)行身份驗(yàn)證和或授權(quán)。提供了多種可用的來(lái)獲取安全相關(guān)的數(shù)據(jù)。 web開(kāi)發(fā)安全框架中的Apache Shiro的應(yīng)用前階段就hadoop的分享了一些內(nèi)容,希望對(duì)新手入門(mén)的朋友有點(diǎn)幫助吧!對(duì)于hadoop新手入門(mén)的,還是比較推薦大快搜索...
摘要:我認(rèn)為無(wú)論是也好,還是其他安全框架也好,其功能主要就分為三部分認(rèn)證授權(quán)加密。的認(rèn)證授權(quán)管理,都需要由負(fù)責(zé)。構(gòu)建環(huán)境主體提交認(rèn)證請(qǐng)求認(rèn)證創(chuàng)建環(huán)境,我們這里使用的是。最后我們使用進(jìn)行認(rèn)證。認(rèn)證我們先說(shuō)這么多,下節(jié)我們來(lái)說(shuō)說(shuō)的簡(jiǎn)單授權(quán)。 showImg(https://segmentfault.com/img/bV8VRT?w=800&h=119); 時(shí)隔這么久終于有時(shí)間更新了,今天和大家分...
摘要:前言由于寫(xiě)的文章已經(jīng)是有點(diǎn)多了,為了自己和大家的檢索方便,于是我就做了這么一個(gè)博客導(dǎo)航。 前言 由于寫(xiě)的文章已經(jīng)是有點(diǎn)多了,為了自己和大家的檢索方便,于是我就做了這么一個(gè)博客導(dǎo)航。 由于更新比較頻繁,因此隔一段時(shí)間才會(huì)更新目錄導(dǎo)航哦~想要獲取最新原創(chuàng)的技術(shù)文章歡迎關(guān)注我的公眾號(hào):Java3y Java3y文章目錄導(dǎo)航 Java基礎(chǔ) 泛型就這么簡(jiǎn)單 注解就這么簡(jiǎn)單 Druid數(shù)據(jù)庫(kù)連接池...
摘要:框架具有輕便,開(kāi)源的優(yōu)點(diǎn),所以本譯見(jiàn)構(gòu)建用戶管理微服務(wù)五使用令牌和來(lái)實(shí)現(xiàn)身份驗(yàn)證往期譯見(jiàn)系列文章在賬號(hào)分享中持續(xù)連載,敬請(qǐng)查看在往期譯見(jiàn)系列的文章中,我們已經(jīng)建立了業(yè)務(wù)邏輯數(shù)據(jù)訪問(wèn)層和前端控制器但是忽略了對(duì)身份進(jìn)行驗(yàn)證。 重拾后端之Spring Boot(四):使用JWT和Spring Security保護(hù)REST API 重拾后端之Spring Boot(一):REST API的搭建...
閱讀 1274·2021-11-24 09:39
閱讀 1530·2021-09-07 09:59
閱讀 3488·2019-08-30 15:54
閱讀 2483·2019-08-30 11:00
閱讀 2675·2019-08-29 15:06
閱讀 2166·2019-08-26 13:52
閱讀 437·2019-08-26 13:24
閱讀 2501·2019-08-26 12:20