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