springboot整合shiro

Shiro 核心功能案例講解 基於SpringBoot 有源碼

從實戰中學習Shiro的用法。本章使用SpringBoot快速搭建項目。整合SiteMesh框架佈局頁面。整合Shiro框架實現用身份認證,受權,數據加密功能。經過本章內容,你將學會用戶權限的分配規則,SpringBoot整合Shiro的配置,Shiro自定義Realm的建立,Shiro標籤式受權和註解式受權的使用場景,等實戰技能,還在等什麼,快來學習吧!css

技術:SpringBoot,Shiro,SiteMesh,Spring,SpringDataJpa,SpringMVC,Bootstrap-sb-admin-1.0.4
說明:前端使用的是Bootstrap-sb-admin模版。注意文章貼出的代碼可能不完整,請以github上源碼爲主,謝謝!
源碼:https://github.com/ITDragonBlog/daydayup/tree/master/Shiro 喜歡的朋友能夠鼓勵(star)下。
效果圖:html

Shiro 功能介紹

四個核心:登陸認證,權限驗證,會話管理,數據加密。
六個支持:支持WEB開發,支持緩存,支持線程併發驗證,支持測試,支持用戶切換,支持"記住我"功能。前端

Authentication :身份認證,也能夠理解爲登陸,驗證用戶身份。
Authorization :權限驗證,也能夠理解爲受權,驗證用戶是否擁有某個權限;即判斷用戶是否能進行什麼操做。
Session Manager :會話管理,用戶登陸後就是一次會話,在退出前,用戶的全部信息都在會話中。
Cryptography :數據加密,保護數據的安全性,常見的有密碼的加鹽加密。
Web Support :支持Web開發。
Caching :緩存,Shiro將用戶信息、擁有的角色/權限數據緩存,以提升程序效率。
Concurrency :支持多線程應用的併發驗證,即在一個線程中開啓另外一個線程,Shiro能把權限自動傳播過去。
Testing :提供測試支持。
Run As :容許一個用戶以另外一個用戶的身份進行訪問;前提是兩個用戶運行切換身份。
Remember Me :記住我,常見的功能,即登陸一次後,在指定時間內免登陸。java

Shiro 功能介紹

Shiro 架構介紹

三個角色:當前用戶 Subject,安全管理器 SecurityManager,權限配置域 Realm。jquery

Subject :表明當前用戶,提供了不少方法,如login和logout。Subject 只是一個門面,與Subject的全部交互都會委託給SecurityManager,SecurityManager纔是真正的執行者;
SecurityManager :安全管理器;Shiro的核心,它負責與Shiro的其餘組件進行交互,即全部與安全有關的操做都會與SecurityManager 交互;且管理着全部的 Subject;
Realm :Shiro 從 Realm 獲取安全數據(如用戶、角色、權限),SecurityManager 要驗證用戶身份,必須要從 Realm 獲取相應的用戶信息,判斷用戶身份是否合法,判斷用戶角色或權限是否受權。git

SpringBoot 整合SiteMesh

SiteMesh 是一個網頁佈局和修飾的框架,利用它能夠將網頁的內容和頁面結構分離,以達到頁面結構共享的目的。github

SiteMesh 統一了頁面的風格,減小了重複代碼,提升了頁面的複用率,是一款值得咱們去學習的框架(也有不少坑)。固然,今天的主角是Shiro,這裏只介紹它的基本用法。
SpringBoot 整合SiteMesh只需二個步驟:
第一步:配置攔截器FIlter,並在web中註冊bean。
第二步:建立裝飾頁面,引入經常使用的css和js文件,統一系統樣式。web

配置攔截器FIlter

指定攔截的URL請求路徑,指定裝飾頁面的文件全路徑,指定不須要攔截的URL請求路徑。這裏攔截全部請求到裝飾頁面,只有登陸頁面和靜態資源不攔截。spring

import org.sitemesh.builder.SiteMeshFilterBuilder; import org.sitemesh.config.ConfigurableSiteMeshFilter; /** * 配置SiteMesh攔截器FIlter,指定裝飾頁面和不須要攔截的路徑 * @author itdragon */ public class WebSiteMeshFilter extends ConfigurableSiteMeshFilter{ @Override protected void applyCustomConfiguration(SiteMeshFilterBuilder builder) { builder.addDecoratorPath("/*", "/WEB-INF/layouts/default.jsp") // 配置裝飾頁面 .addExcludedPath("/static/*") // 靜態資源不攔截 .addExcludedPath("/login**"); // 登陸頁面不攔截 } }
import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * web.xml 配置 * @author itdragon */ @Configuration public class WebConfig { @Bean // 配置siteMesh3 public FilterRegistrationBean siteMeshFilter(){ FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(); WebSiteMeshFilter siteMeshFilter = new WebSiteMeshFilter(); filterRegistrationBean.setFilter(siteMeshFilter); return filterRegistrationBean; } }

建立裝飾頁面

SiteMesh語法
<sitemesh:write property='title'/> : 被修飾頁面title的內容會在這裏顯示。
<sitemesh:write property='head'/> : 被修飾頁面head的內容會在這裏顯示,除了title。
<sitemesh:write property='body'/> : 被修飾頁面body的內容會在這裏顯示。
須要注意的是:SiteMesh的jar有OpenSymphony(最新版是2009年)和Apache(最新版是2015年),二者用法是有差別的。筆者選擇的是Apache版本的jar。sql

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <meta name="viewport" content="initial-scale=1.0, width=device-width, user-scalable=no" /> <title>ITDragon系統-<sitemesh:write property='title'/></title> <link type="image/x-icon" href="images/favicon.ico" rel="shortcut icon"> <c:set var="ctx" value="${pageContext.request.contextPath}" /> <link href="${ctx}/static/sb-admin-1.0.4/css/bootstrap.min.css" rel="stylesheet"> <link href="${ctx}/static/sb-admin-1.0.4/css/sb-admin.css" rel="stylesheet"> <sitemesh:write property='head'/> </head> <body> <div id="wrapper"> <%@ include file="/WEB-INF/layouts/header.jsp"%> <div class='mainBody'> <sitemesh:write property='body'/> </div> </div> <script src="${ctx}/static/sb-admin-1.0.4/js/jquery.js"></script> <script src="${ctx}/static/sb-admin-1.0.4/js/bootstrap.min.js"></script> </body> </html>

SpringBoot 整合Shiro

這是本章的核心知識點,SpringBoot 整合Shiro 有三個步驟:
第一步:建立實體類:用戶,角色,權限。肯定三者關係,以方便Realm的受權工做。
第二步:建立自定義安全數據源Realm:負責用戶登陸認證,用戶操做受權。
第三步:建立Spring整合Shiro配置類:配置攔截規則,生命週期,安全管理器,安全數據源,等。

建立實體類

實體類:User,SysRole,SysPermission。
權限設計思路:
1). 角色表肯定系統菜單資源,權限表肯定菜單操做資源。
2). 用戶主要經過角色來獲取權限,且一個用戶能夠擁有多個角色(不推薦,但必須支持該功能)。
3). 一個角色能夠擁有多個權限,同時也能夠有用多個用戶。
4). 一個權限能夠被多個角色使用。
5). 工做都是從易到難,咱們能夠先從「一個用戶擁有一個角色,一個角色擁有多個權限」開始。
有了上面的分析,三個實體類代碼以下,省略了get/set方法。

import java.util.List; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.ManyToMany; import javax.persistence.Table; import javax.persistence.Transient; /** * 用戶實體類 * @author itdragon */ @Table(name="itdragon_user_shiro") @Entity public class User { @Id @GeneratedValue(strategy=GenerationType.AUTO) private Long id; // 自增加主鍵,默認ID爲1的帳號爲超級管理員 private String account; // 登陸的帳號 private String userName; // 註冊的暱稱 @Transient private String plainPassword; // 登陸時的密碼,不持久化到數據庫 private String password; // 加密後的密碼 private String salt; // 用於加密的鹽 private String iphone; // 手機號 private String email; // 郵箱 private String platform; // 用戶來自的平臺 private String createdDate; // 用戶註冊時間 private String updatedDate; // 用戶最後一次登陸時間 @ManyToMany(fetch=FetchType.EAGER) @JoinTable(name = "SysUserRole", joinColumns = { @JoinColumn(name = "uid") }, inverseJoinColumns ={@JoinColumn(name = "roleId") }) private List<SysRole> roleList; // 一個用戶擁有多個角色 private Integer status; // 用戶狀態,0表示用戶已刪除 }
import java.util.List; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.ManyToMany; import javax.persistence.Table; /** * 角色表,決定用戶能夠訪問的頁面 * @author itdragon */ @Table(name="itdragon_sysrole") @Entity public class SysRole { @Id @GeneratedValue private Integer id; private String role; // 角色 private String description; // 角色描述 private Boolean available = Boolean.FALSE; // 默認不可用 //角色 -- 權限關係:多對多關係; 取出這條數據時,把它關聯的數據也同時取出放入內存中 @ManyToMany(fetch=FetchType.EAGER) @JoinTable(name="SysRolePermission",joinColumns={@JoinColumn(name="roleId")},inverseJoinColumns={@JoinColumn(name="permissionId")}) private List<SysPermission> permissions; // 用戶 - 角色關係:多對多關係; @ManyToMany @JoinTable(name="SysUserRole",joinColumns={@JoinColumn(name="roleId")},inverseJoinColumns={@JoinColumn(name="uid")}) private List<User> users; }
import java.util.List; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.ManyToMany; import javax.persistence.Table; /** * 權限表,決定用戶的具體操做 * @author itdragon */ @Table(name = "itdragon_syspermission") @Entity public class SysPermission { @Id @GeneratedValue private Integer id; private String name; // 名稱 private String url; // 資源路徑 private String permission; // 權限字符串 如:employees:create,employees:update,employees:delete private Boolean available = Boolean.FALSE; // 默認不可用 @ManyToMany @JoinTable(name = "SysRolePermission", joinColumns = { @JoinColumn(name = "permissionId") }, inverseJoinColumns = {@JoinColumn(name = "roleId") }) private List<SysRole> roles; }

建立自定義安全數據源Realm

Shiro 從 Realm 獲取安全數據(如用戶、角色、權限),SecurityManager 身份認證和權限認證都是從Realm中獲取相應的用戶信息,而後作比較判斷是否有身份登陸,是否有權限操做。
Shiro 支持多個Realm。同時也有不一樣的認證策略:
FirstSuccessfulStrategy : 只要有一個Realm成功就返回,後面的忽略;
AtLeastOneSuccessfulStrategy : 只要有一個Realm成功就經過,返回全部認證成功的信息,默認;
AllSuccessfulStrategy : 必須全部Realm都成功纔算經過

import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.SimpleAuthenticationInfo; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; import org.apache.shiro.util.ByteSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import com.itdragon.pojo.SysPermission; import com.itdragon.pojo.SysRole; import com.itdragon.pojo.User; import com.itdragon.service.UserService; /** * 自定義安全數據Realm,重點 * @author itdragon */ public class ITDragonShiroRealm extends AuthorizingRealm { private static final transient Logger log = LoggerFactory.getLogger(ITDragonShiroRealm.class); @Autowired private UserService userService; /** * 受權 */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { log.info("^^^^^^^^^^^^^^^^^^^^ ITDragon 配置當前用戶權限"); String username = (String) principals.getPrimaryPrincipal(); User user = userService.findByAccount(username); if(null == user){ return null; } SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); for (SysRole role : user.getRoleList()) { authorizationInfo.addRole(role.getRole()); // 添加角色 for (SysPermission permission : role.getPermissions()) { authorizationInfo.addStringPermission(permission.getPermission()); // 添加具體權限 } } return authorizationInfo; } /** * 身份認證 */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { log.info("^^^^^^^^^^^^^^^^^^^^ ITDragon 認證用戶身份信息"); String username = (String) token.getPrincipal(); // 獲取用戶登陸帳號 User userInfo = userService.findByAccount(username); // 經過帳號查加密後的密碼和鹽,這裏通常從緩存讀取 if(null == userInfo){ return null; } // 1). principal: 認證的實體信息. 能夠是 username, 也能夠是數據表對應的用戶的實體類對象. Object principal = username; // 2). credentials: 加密後的密碼. Object credentials = userInfo.getPassword(); // 3). realmName: 當前 realm 對象的惟一名字. 調用父類的 getName() 方法 String realmName = getName(); // 4). credentialsSalt: 鹽值. 注意類型是ByteSource ByteSource credentialsSalt = ByteSource.Util.bytes(userInfo.getSalt()); SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(principal, credentials, credentialsSalt, realmName); return info; } }

建立Spring整合Shiro配置類

第一步:配置Shiro攔截器,指定URL請求的權限。首先靜態資源和登陸請求匿名訪問,而後是用戶登出操做,最後是全部請求都需身份認證。Shiro攔截器優先級是從上到下,切勿將/**=authc,放在前面。
第二步:配置Shiro生命週期處理器,
第三步:配置自定義Realm,負責身份認證和受權。
第四步:配置安全管理器SecurityManager,Shiro的核心。

import java.util.LinkedHashMap; import java.util.Map; import org.apache.shiro.authc.credential.HashedCredentialsMatcher; import org.apache.shiro.spring.LifecycleBeanPostProcessor; import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.DependsOn; /** * Shiro 配置,重點 * @author itdragon */ @Configuration public class ShiroSpringConfig { private static final transient Logger log = LoggerFactory.getLogger(ShiroSpringConfig.class); /** * 配置攔截器 * * 定義攔截URL權限,優先級從上到下 * 1). anon : 匿名訪問,無需登陸 * 2). authc : 登陸後才能訪問 * 3). logout: 登出 * 4). roles : 角色過濾器 * * URL 匹配風格 * 1). ?:匹配一個字符,如 /admin? 將匹配 /admin1,但不匹配 /admin 或 /admin/; * 2). *:匹配零個或多個字符串,如 /admin* 將匹配 /admin 或/admin123,但不匹配 /admin/1; * 2). **:匹配路徑中的零個或多個路徑,如 /admin/** 將匹配 /admin/a 或 /admin/a/b * * 配置身份驗證成功,失敗的跳轉路徑 */ @Bean public ShiroFilterFactoryBean shirFilter(DefaultWebSecurityManager securityManager) { log.info("^^^^^^^^^^^^^^^^^^^^ ITDragon 配置Shiro攔截工廠"); ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(securityManager); Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>(); filterChainDefinitionMap.put("/static/**", "anon"); // 靜態資源匿名訪問 filterChainDefinitionMap.put("/employees/login", "anon");// 登陸匿名訪問 filterChainDefinitionMap.put("/logout", "logout"); // 用戶退出,只需配置logout便可實現該功能 filterChainDefinitionMap.put("/**", "authc"); // 其餘路徑均須要身份認證,通常位於最下面,優先級最低 shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); shiroFilterFactoryBean.setLoginUrl("/login"); // 登陸的路徑 shiroFilterFactoryBean.setSuccessUrl("/dashboard"); // 登陸成功後跳轉的路徑 shiroFilterFactoryBean.setUnauthorizedUrl("/403"); // 驗證失敗後跳轉的路徑 return shiroFilterFactoryBean; } /** * 配置Shiro生命週期處理器 */ @Bean public LifecycleBeanPostProcessor lifecycleBeanPostProcessor(){ return new LifecycleBeanPostProcessor(); } /** * 自動建立代理類,若不添加,Shiro的註解可能不會生效。 */ @Bean @DependsOn({"lifecycleBeanPostProcessor"}) public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator(){ DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator(); advisorAutoProxyCreator.setProxyTargetClass(true); return advisorAutoProxyCreator; } /** * 開啓Shiro的註解 */ @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(){ AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); authorizationAttributeSourceAdvisor.setSecurityManager(securityManager()); return authorizationAttributeSourceAdvisor; } /** * 配置加密匹配,使用MD5的方式,進行1024次加密 */ @Bean public HashedCredentialsMatcher hashedCredentialsMatcher() { HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(); hashedCredentialsMatcher.setHashAlgorithmName("MD5"); hashedCredentialsMatcher.setHashIterations(1024); return hashedCredentialsMatcher; } /** * 自定義Realm,能夠多個 */ @Bean public ITDragonShiroRealm itDragonShiroRealm() { ITDragonShiroRealm itDragonShiroRealm = new ITDragonShiroRealm(); itDragonShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher()); return itDragonShiroRealm; } /** * SecurityManager 安全管理器;Shiro的核心 */ @Bean public DefaultWebSecurityManager securityManager() { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(itDragonShiroRealm()); return securityManager; } }

實現業務邏輯

系統有四個菜單:控制面板 Dashboard,員工管理 Employees,權限管理 Permissions,角色管理 Roles 。
系統有三個角色:超級管理員 admin, 經理 manager, 普通員工 staff 。
業務的邏輯要求:
1) admin角色能夠訪問全部菜單,manager角色除了Roles菜單外均可以訪問,staff角色只能訪問Dashboard和Employees菜單 。
2) admin角色擁有刪除用戶信息的權限,其餘兩個角色沒有權限。

實現業務邏輯步驟:
第一步:模擬數據,建立用戶,角色,權限數據。
第二步:左側菜單權限配置,須要用到Shiro的標籤式受權。
第三步:在刪除用戶的Controller層方法上配置操做權限,須要用到Shiro的註解式受權。
第四步:權限驗證失敗統一處理。

配置數據

sql文件路徑:https://github.com/ITDragonBlog/daydayup/tree/master/Shiro/springboot-shiro/sql
建議先執行sql文件,再啓動項目。
用戶密碼一般採用加鹽加密的方式,筆者採用MD5的加密方式,以UUID做爲鹽,進行1024次加密。代碼以下:

import java.util.UUID; import org.apache.shiro.crypto.hash.SimpleHash; import org.apache.shiro.util.ByteSource; import com.itdragon.pojo.User; /** * 工具類 * @author itdragon */ public class ItdragonUtils { private static final String ALGORITHM_NAME = "MD5"; private static final Integer HASH_ITERATIONS = 1024; public static void entryptPassword(User user) { String salt = UUID.randomUUID().toString(); String temPassword = user.getPlainPassword(); Object md5Password = new SimpleHash(ALGORITHM_NAME, temPassword, ByteSource.Util.bytes(salt), HASH_ITERATIONS); user.setSalt(salt); user.setPassword(md5Password.toString()); } }

左側菜單權限配置

系統使用了SiteMesh框架,左側菜單頁面屬於修飾頁面的一部分。只須要在一個文件中添加shiro的標籤,就能夠在整個系統生效,耦合性很低。
<shiro:guest> : 容許遊客訪問的代碼塊
<shiro:user> : 容許已經驗證或者經過"記住我"登陸的用戶才能訪問的代碼塊。
<shiro:authenticated> : 只有經過登陸操做認證身份,而並不是經過"記住我"登陸的用戶才能訪問的代碼塊。
<shiro:notAuthenticated> : 未登陸的用戶顯示的代碼塊。
<shiro:principal> : 顯示當前登陸的用戶信息。
<shiro:hasRole name="admin"> : 只有擁有admin角色的用戶才能訪問的代碼塊。
<shiro:hasAnyRoles name="admin,manager"> : 只有擁有admin或者manager角色的用戶才能訪問的代碼塊。
<shiro:lacksRole name="admin"> : 沒有admin角色的用戶顯示的代碼塊
<shiro:hasPermission name="admin:delete"> : 只有擁有"admin:delete"權限的用戶才能訪問的代碼塊。
<shiro:lacksPermission name="admin:delete"> : 沒有"admin:delete"權限的用戶顯示的代碼塊。

<div class="collapse navbar-collapse navbar-ex1-collapse"> <ul class="nav navbar-nav side-nav itdragon-nav"> <li class="active"> <a href="/dashboard"><i class="fa fa-fw fa-dashboard"></i> Dashboard</a> </li> <li> <a href="/employees"><i class="fa fa-fw fa-bar-chart-o"></i> Employees</a> </li> <!-- 只有角色爲admin或manager的用戶纔有權限訪問 --> <shiro:hasAnyRoles name="admin,manager"> <li> <a href="/permission"><i class="fa fa-fw fa-table"></i> Permissions</a> </li> </shiro:hasAnyRoles> <!-- 只有角色爲admin的用戶纔有權限訪問 --> <shiro:hasRole name="admin"> <li> <a href="/roles"><i class="fa fa-fw fa-file"></i> Roles</a> </li> </shiro:hasRole> </ul> </div>

在操做上添加權限

Shiro常見的權限註解有:
@RequiresAuthentication : 表示當前 Subject 已經認證登陸的用戶才能調用的代碼塊。
@RequiresUser : 表示當前 Subject 已經身份驗證或經過記住我登陸的。
@RequiresGuest : 表示當前 Subject 沒有身份驗證,便是遊客身份。
@RequiresRoles(value={"admin", "user"}, logical=Logical.AND) : 表示當前 Subject 須要角色 admin和user
@RequiresPermissions (value={"user:update", "user:delete"}, logical= Logical.OR) : 表示當前 Subject 須要權限 user:update或user:delete。
這裏值得注意的是:若是你的註解沒有生效,極可能沒有配置Shiro註解開啓的問題。

@RequestMapping(value = "delete/{id}") @RequiresPermissions(value={"employees:delete"}) public String delete(@PathVariable("id") Long id, RedirectAttributes redirectAttributes) { userService.deleteUser(id); redirectAttributes.addFlashAttribute("message", "刪除用戶成功"); return "redirect:/employees"; }

權限驗證失敗統一處理

Shiro提供權限驗證失敗跳轉頁面的功能,但這個邏輯是不友好的。咱們須要統一處理權限驗證失敗,並返回執行失敗的頁面。

import org.apache.shiro.web.util.WebUtils; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.servlet.mvc.support.RedirectAttributes; /** * 異常統一處理 * @author itdragon */ @ControllerAdvice public class ExceptionController { @ExceptionHandler(org.apache.shiro.authz.AuthorizationException.class) public String handleException(RedirectAttributes redirectAttributes, Exception exception, HttpServletRequest request) { redirectAttributes.addFlashAttribute("message", "抱歉!您沒有權限執行這個操做,請聯繫管理員!"); String url = WebUtils.getRequestUri(request); return "redirect:/" + url.split("/")[1]; // 請求的規則 : /page/operate } }

Shiro和SpringSecurity

1) Shiro使用更簡單,更容易上手。
2) Spring Security功能更強大,和Spring無縫整合,但學習門檻比Shiro高。
3) 個人建議是兩個均可以學習,誰知道公司下一秒會選擇什麼框架。。。

總結

1) Shiro 四個核心功能:身份認證,受權,數據加密,Seesion管理。
2) Shiro 三個重要角色:Subject,SecurityManager,Realm。
3) Shiro 五個常見開發:自定義Realm,配置攔截器,標籤式受權控制菜單,註解式受權控制操做,權限不夠異常統一處理。
4) 項目搭建推薦從攔截器開始,而後再是身份認證,角色權限認證,操做權限認證。
5) Shiro 其餘知識後續介紹。

到這裏Shiro 核心功能案例講解 基於SpringBoot 的文章就寫完了,一個基本的系統也搭完了。還有不少缺陷和建議,不吝賜教!若是文章對你有幫助,能夠點個"推薦",也能夠"關注"我,得到更多豐富的知識。

其餘知識查考文獻

Shiro 權限註解 :http://blog.csdn.net/w_stronger/article/details/73109248

Spring @ControllerAdvice註解 : http://blog.csdn.net/jackfrued/article/details/76710885

bootstrap 模塊頁面 : https://startbootstrap.com/template-categories/all/

出處:http://www.cnblogs.com/itdragon/

簡介:天天都在進步,每週都在總結,架構師的修羅之路!你的一個點贊,一句留言,就可讓博主開心一笑,充滿動力!最近由於生活緣由沒能繼續學習,如今羞愧地從新開始。若文章對你有很大的幫助,能夠捐助一下麼

版權:本文版權歸做者和博客園共有,歡迎轉載,但未經做者贊成必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接,不然保留追究法律責任的權利。
相關文章
相關標籤/搜索