03-11-動吧旅遊生態系統-Shiro
03-11-動吧旅遊生態系統-Shiro
1Shiro安全框架簡介
1.1Shiro概述
Shiro是apache旗下一個開源安全框架(http://shiro.apache.org/),它將軟體系統的安全認證相關的功能抽取出來,實現使用者身份認證,許可權授權、加密、會話管理等功能,組成了一個通用的安全認證框架。使用shiro就可以非常快速的完成認證、授權等功能的開發,降低系統成本。
使用者在進行資源訪問時,要求系統要對使用者進行許可權控制,其具體流程如圖-1所示:
圖-1
1.2Shiro概要架構
在概念層面,Shiro 架構包含三個主要的理念,如圖-2所示:
圖-2
其中:
1)Subject :主體物件,負責提交使用者認證和授權資訊。
2)SecurityManager:安全管理器,負責認證,授權等業務實現。
3)Realm:領域物件,負責從資料層獲取業務資料。
1.3Shiro詳細架構
Shiro框架進行許可權管理時,要涉及到的一些核心物件,主要包括:認證管理物件,授權管理物件,會話管理物件,快取管理物件,加密管理物件以及Realm管理物件(領域物件:負責處理認證和授權領域的資料訪問題)等,其具體架構如圖-3所示:
圖-3
其中:
1)Subject(主體):與軟體互動的一個特定的實體(使用者、第三方服務等)。
2)SecurityManager(安全管理器) :Shiro 的核心,用來協調管理元件工作。
3)Authenticator(認證管理器):負責執行認證操作。
4)Authorizer(授權管理器):負責授權檢測。
5)SessionManager(會話管理):負責建立並管理使用者 Session 生命週期,提供一個強有力的 Session 體驗。
6)SessionDAO:代表 SessionManager 執行 Session 持久(CRUD)動作,它允許任何儲存的資料掛接到 session 管理基礎上。
7)CacheManager(快取管理器):提供建立快取例項和管理快取生命週期的功能。
8)Cryptography(加密管理器):提供了加密方式的設計及管理。
9)Realms(領域物件):是shiro和你的應用程式安全資料之間的橋樑。
2Shiro框架認證攔截實現(filter)
2.1Shiro基本環境配置
2.1.1新增shiro依賴
實用spring整合shiro時,需要在pom.xml中新增如下依賴:
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.5.3</version>
</dependency>
2.1.2Shiro核心物件配置
基於SpringBoot 實現的專案中,沒有提供shiro的自動化配置,需要我們自己配置。
第一步:建立SpringShiroConfig類。關鍵程式碼如下:
package com.cy.pj.common.config;
/**@Configuration 註解描述的類為一個配置物件,
* 此物件也會交給spring管理
*/
@Configuration
public class SpringShiroConfig {
}
第二步:在Shiro配置類中新增SecurityManager配置(這裡一定要使用org.apache.shiro.mgt.SecurityManager這個介面物件),關鍵程式碼如下:
@Bean
public SecurityManager securityManager() {
DefaultWebSecurityManager sManager=
new DefaultWebSecurityManager();
return sManager;
}
第三步: 在Shiro配置類中新增ShiroFilterFactoryBean物件的配置。通過此物件設定資源匿名訪問、認證訪問。關鍵程式碼如下:
@Bean
public ShiroFilterFactoryBean shiroFilterFactory (
SecurityManager securityManager) {
ShiroFilterFactoryBean sfBean=
new ShiroFilterFactoryBean();
sfBean.setSecurityManager(securityManager);
//定義map指定請求過濾規則(哪些資源允許匿名訪問,哪些必須認證訪問)
LinkedHashMap<String,String> map= new LinkedHashMap<>();
//靜態資源允許匿名訪問:"anon"
map.put("/bower_components/**","anon");
map.put("/build/**","anon");
map.put("/dist/**","anon");
map.put("/plugins/**","anon");
//除了匿名訪問的資源,其它都要認證("authc")後訪問
map.put("/**","authc");
sfBean.setFilterChainDefinitionMap(map);
return sfBean;
}
其配置過程中,物件關係如下圖-4所示:
圖-4
2.2Shiro登陸頁面呈現
2.2.1服務端Controller實現
▪業務描述及設計實現
當服務端攔截到使用者請求以後,判定此請求是否已經被認證,假如沒有認證應該先跳轉到登入頁面。
▪關鍵程式碼分析及實現.
第一步:在PageController中新增一個呈現登入頁面的方法,關鍵程式碼如下:
@RequestMapping("doLoginUI")
public String doLoginUI(){
return "login";
}
第二步:修改SpringShiroConfig類中shiroFilterFactorybean的配置,新增登陸url的設定。關鍵程式碼見sfBean.setLoginUrl("/doLoginUI")部分。
@Bean
public ShiroFilterFactoryBean shiroFilterFactory (
SecurityManager securityManager) {
ShiroFilterFactoryBean sfBean=
new ShiroFilterFactoryBean();
sfBean.setSecurityManager(securityManager);
sfBean.setLoginUrl("/doLoginUI");
//定義map指定請求過濾規則(哪些資源允許匿名訪問,
哪些必須認證訪問)
LinkedHashMap<String,String> map=
new LinkedHashMap<>();
//靜態資源允許匿名訪問:"anon"
map.put("/bower_components/**","anon");
map.put("/modules/**","anon");
map.put("/dist/**","anon");
map.put("/plugins/**","anon");
//除了匿名訪問的資源,其它都要認證("authc")後訪問
map.put("/**","authc");
sfBean.setFilterChainDefinitionMap(map);
return sfBean;
}
2.2.2客戶端頁面實現
▪業務描述及設計實現。
在/templates/pages/新增一個login.html頁面,然後將專案部署到web伺服器,並啟動測試執行.
▪關鍵程式碼分析及實現。
具體程式碼見專案中login.html。
3Shiro框架認證業務實現
3.1認證流程分析
身份認證即判定使用者是否是系統的合法使用者,使用者訪問系統資源時的認證(對使用者身份資訊的認證)流程圖-5所示:
圖-5
其中認證流程分析如下:
1)系統呼叫subject的login方法將使用者資訊提交給SecurityManager
2)SecurityManager將認證操作委託給認證器物件Authenticator
3)Authenticator將使用者輸入的身份資訊傳遞給Realm。
4)Realm訪問資料庫獲取使用者資訊然後對資訊進行封裝並返回。
5)Authenticator 對realm返回的資訊進行身份認證。
思考:不使用shiro框架如何完成認證操作?filter,intercetor。
3.2認證服務端實現
3.2.1核心業務分析
認證業務API處理流程分析,如圖-6所示:
圖-6
3.2.2DAO介面定義
▪業務描述及設計實現。
在使用者資料層物件SysUserDao中,按特定條件查詢使用者資訊,並對其進行封裝。
▪關鍵程式碼分析及實現。
在SysUserDao介面中,新增根據使用者名稱獲取使用者物件的方法,關鍵程式碼如下:
SysUser findUserByUserName(String username)。
3.2.3Mapper元素定義
▪業務描述及設計實現。
根據SysUserDao中定義的方法,在SysUserMapper檔案中新增元素定義。
▪關鍵程式碼分析及實現。
基於使用者名稱獲取使用者物件的方法,關鍵程式碼如下:
<select id="findUserByUserName"
resultType="com.cy.pj.sys.entity.SysUser">
select *
from sys_users
where username=#{username}
</select>
3.2.4Service介面及實現
▪業務描述及設計實現。
本模組的業務在Realm型別的物件中進行實現,我們編寫realm時,要繼承
AuthorizingRealm並重寫相關方法,完成認證及授權業務資料的獲取及封裝。
▪關鍵程式碼分析及實現。
第一步:定義ShiroUserRealm類,關鍵程式碼如下:
package com.cy.pj.sys.service.realm;
@Service
public class ShiroUserRealm extends AuthorizingRealm {
@Autowired
private SysUserDao sysUserDao;
/**
* 設定憑證匹配器(與使用者新增操作使用相同的加密演算法)
*/
@Override
public void setCredentialsMatcher(
CredentialsMatcher credentialsMatcher) {
//構建憑證匹配物件
HashedCredentialsMatcher cMatcher=
new HashedCredentialsMatcher();
//設定加密演算法
cMatcher.setHashAlgorithmName("MD5");
//設定加密次數
cMatcher.setHashIterations(1);
super.setCredentialsMatcher(cMatcher);
}
/**
* 通過此方法完成認證資料的獲取及封裝,系統
* 底層會將認證資料傳遞認證管理器,由認證
* 管理器完成認證操作。
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken token)
throws AuthenticationException {
//1.獲取使用者名稱(使用者頁面輸入)
UsernamePasswordToken upToken=
(UsernamePasswordToken)token;
String username=upToken.getUsername();
//2.基於使用者名稱查詢使用者資訊
SysUser user=
sysUserDao.findUserByUserName(username);
//3.判定使用者是否存在
if(user==null)
throw new UnknownAccountException();
//4.判定使用者是否已被禁用。
if(user.getValid()==0)
throw new LockedAccountException();
//5.封裝使用者資訊
ByteSource credentialsSalt=
ByteSource.Util.bytes(user.getSalt());
//記住:構建什麼物件要看方法的返回值
SimpleAuthenticationInfo info=
new SimpleAuthenticationInfo(
user,//principal (身份)
user.getPassword(),//hashedCredentials
credentialsSalt, //credentialsSalt
getName());//realName
//6.返回封裝結果
return info;//返回值會傳遞給認證管理器(後續
//認證管理器會通過此資訊完成認證操作)
}
....
}
第二步:對此realm,需要在SpringShiroConfig配置類中,注入給SecurityManager物件,修改securityManager方法,見黃色背景部分,例如:
@Bean
public SecurityManager securityManager(Realm realm) {
DefaultWebSecurityManager sManager=
new DefaultWebSecurityManager();
sManager.setRealm(realm);
return sManager;
}
3.2.5Controller 類實現
▪業務描述及設計實現。
在此物件中定義相關方法,處理客戶端的登陸請求,例如獲取使用者名稱,密碼等然後提交該shiro框架進行認證。
▪關鍵程式碼分析及實現。
第一步:在SysUserController中新增處理登陸的方法。關鍵程式碼如下:
@RequestMapping("doLogin")
public JsonResult doLogin(String username,String password){
//1.獲取Subject物件
Subject subject=SecurityUtils.getSubject();
//2.通過Subject提交使用者資訊,交給shiro框架進行認證操作
//2.1對使用者進行封裝
UsernamePasswordToken token=
new UsernamePasswordToken(
username,//身份資訊
password);//憑證資訊
//2.2對使用者資訊進行身份認證
subject.login(token);
//分析:
//1)token會傳給shiro的SecurityManager
//2)SecurityManager將token傳遞給認證管理器
//3)認證管理器會將token傳遞給realm
return new JsonResult("login ok");
}
第二步:修改shiroFilterFactory的配置,對/user/doLogin這個路徑進行匿名訪問的配置,檢視如下黃色標記部分的程式碼:
@Bean
public ShiroFilterFactoryBean shiroFilterFactory (
SecurityManager securityManager) {
ShiroFilterFactoryBean sfBean=
new ShiroFilterFactoryBean();
sfBean.setSecurityManager(securityManager);
//假如沒有認證請求先訪問此認證的url
sfBean.setLoginUrl("/doLoginUI");
//定義map指定請求過濾規則(哪些資源允許匿名訪問,哪些必須認證訪問)
LinkedHashMap<String,String> map=
new LinkedHashMap<>();
//靜態資源允許匿名訪問:"anon"
map.put("/bower_components/**","anon");
map.put("/build/**","anon");
map.put("/dist/**","anon");
map.put("/plugins/**","anon");
map.put("/user/doLogin","anon"); //authc表示,除了匿名訪問的資源,其它都要認證("authc")後才能訪問訪問
map.put("/**","authc");
sfBean.setFilterChainDefinitionMap(map);
return sfBean;
}
第三步:當我們在執行登入操作時,為了提高使用者體驗,可對系統中的異常資訊進行處理,例如,在統一異常處理類中新增如下方法:
@ExceptionHandler(ShiroException.class)
@ResponseBody
public JsonResult doHandleShiroException(
ShiroException e) {
JsonResult r=new JsonResult();
r.setState(0);
if(e instanceof UnknownAccountException) {
r.setMessage("賬戶不存在");
}else if(e instanceof LockedAccountException) {
r.setMessage("賬戶已被禁用");
}else if(e instanceof IncorrectCredentialsException) {
r.setMessage("密碼不正確");
}else if(e instanceof AuthorizationException) {
r.setMessage("沒有此操作許可權");
}else {
r.setMessage("系統維護中");
}
e.printStackTrace();
return r;
}
3.3認證客戶端實現
3.3.1編寫使用者登陸頁面
在/templates/pages/目錄下新增登陸頁面(login.html)。
3.3.2非同步登陸操作實現
點選登入操作時,將輸入的使用者名稱,密碼非同步提交到服務端。
$(function () {
$(".login-box-body").on("click",".btn",doLogin);
});
function doLogin(){
var params={
username:$("#usernameId").val(),
password:$("#passwordId").val()
}
var url="user/doLogin";
$.post(url,params,function(result){
if(result.state==1){
//跳轉到indexUI對應的頁面
location.href="doIndexUI?t="+Math.random();
}else{
$(".login-box-msg").html(result.message);
}
});
}
3.4退出操作配置實現
在SpringShiroConfig配置類中,修改過濾規則,新增黃色標記部分程式碼的配置,請看如下程式碼:
@Bean
public ShiroFilterFactoryBean shiroFilterFactory(
SecurityManager securityManager) {
ShiroFilterFactoryBean sfBean=
new ShiroFilterFactoryBean();
sfBean.setSecurityManager(securityManager);
//假如沒有認證請求先訪問此認證的url
sfBean.setLoginUrl("/doLoginUI");
//定義map指定請求過濾規則(哪些資源允許匿名訪問,哪些必須認證訪問)
LinkedHashMap<String,String> map=new LinkedHashMap<>();
//靜態資源允許匿名訪問:"anon"
map.put("/bower_components/**","anon");
map.put("/build/**","anon");
map.put("/dist/**","anon");
map.put("/plugins/**","anon");
map.put("/user/doLogin","anon");
map.put("/doLogout","logout");
//除了匿名訪問的資源,其它都要認證("authc")後訪問
map.put("/**","authc");
sfBean.setFilterChainDefinitionMap(map);
return sfBean;
}
4Shiro框架授權過程實現
4.1授權流程分析
授權即對使用者資源訪問的授權(是否允許使用者訪問此資源),使用者訪問系統資源時的授權流程如圖-7所示:
圖-7
其中授權流程分析如下:
1)系統呼叫subject相關方法將使用者資訊(例如isPermitted)遞交給SecurityManager。
2)SecurityManager將許可權檢測操作委託給Authorizer物件。
3)Authorizer將使用者資訊委託給realm。
4)Realm訪問資料庫獲取使用者許可權資訊並封裝。
5)Authorizer對使用者授權資訊進行判定。
思考:思考不使用shiro如何完成授權操作?intercetor,aop。
4.2新增授權配置
在SpringShiroConfig配置類中,新增授權時的相關配置:
第一步:配置bean物件的生命週期管理(SpringBoot可以不配置)。
@Bean
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
第二步: 通過如下配置要為目標業務物件建立代理物件(SpringBoot中可省略)。
@DependsOn("lifecycleBeanPostProcessor")
@Bean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
return new DefaultAdvisorAutoProxyCreator();
}
第三步:配置advisor物件,shiro框架底層會通過此物件的matchs方法返回值(類似切入點)決定是否建立代理物件,進行許可權控制。
@Bean
public AuthorizationAttributeSourceAdvisor
authorizationAttributeSourceAdvisor (
SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor advisor=
new AuthorizationAttributeSourceAdvisor();
advisor.setSecurityManager(securityManager);
return advisor;
}
說明:使用框架最重要的尊重規則,框架規則指定了什麼方式就使用什麼方式。
4.3授權服務端實現
4.3.1核心業務分析
授權時,服務端核心業務以及API分析,如圖-8所示:
圖-8
4.3.2Dao實現
▪業務描述及設計實現。
基於登陸使用者ID,認證資訊獲取登陸使用者的許可權資訊,並進行封裝。
▪關鍵程式碼分析及實現。
第一步:在SysUserRoleDao中定義基於使用者id查詢角色id的方法(假如方法已經存在則無需再寫),關鍵程式碼如下:
List<Integer> findRoleIdsByUserId(Integer id);
第二步:在SysRoleMenuDao中定義基於角色id查詢選單id的方法,關鍵程式碼如下:
List<Integer> findMenuIdsByRoleIds(
@Param("roleIds")List<Integer> roleIds);
第三步:在SysMenuDao中基於選單id查詢許可權標識的方法,關鍵程式碼如下:
List<String> findPermissions(
@Param("menuIds")
List<Integer> menuIds);
4.3.3Mapper實現
▪業務描述及設計實現。
基於Dao中方法,定義對映元素。
▪關鍵程式碼分析及實現。
第一步:在SysUserRoleMapper中定義findRoleIdsByUserId元素。關鍵程式碼如下:
<select id="findRoleIdsByUserId"
resultType="int">
select role_id
from sys_user_roles
where user_id=#{userId}
</select>
第二步:在SysRoleMenuMapper中定義findMenuIdsByRoleIds元素。關鍵程式碼如下:
<select id="findMenuIdsByRoleIds"
resultType="int">
select menu_id
from sys_role_menus
where role_id in
<foreach collection="roleIds"
open="("
close=")"
separator=","
item="item">
#{item}
</foreach>
</select>
第三步:在SysMenuMapper中定義findPermissions元素,關鍵程式碼如下:
<select id="findPermissions"
resultType="string">
select permission <!-- sys:user:update -->
from sys_menus
where id in
<foreach collection="menuIds"
open="("
close=")"
separator=","
item="item">
#{item}
</foreach>
</select>
4.3.4Service實現
▪業務描述及設計實現。
在ShiroUserReam類中,重寫物件realm的doGetAuthorizationInfo方法,並完成使用者許可權資訊的獲取以及封裝,最後將資訊傳遞給授權管理器完成授權操作。
▪關鍵程式碼分析及實現。
修改ShiroUserRealm類中的doGetAuthorizationInfo方法,關鍵程式碼如下:
@Service
public class ShiroUserRealm extends AuthorizingRealm {
@Autowired
private SysUserDao sysUserDao;
@Autowired
private SysUserRoleDao sysUserRoleDao;
@Autowired
private SysRoleMenuDao sysRoleMenuDao;
@Autowired
private SysMenuDao sysMenuDao;
/**通過此方法完成授權資訊的獲取及封裝*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(
PrincipalCollection principals) {
//1.獲取登入使用者資訊,例如使用者id
SysUser user=(SysUser)principals.getPrimaryPrincipal();
Integer userId=user.getId();
//2.基於使用者id獲取使用者擁有的角色(sys_user_roles)
List<Integer> roleIds=
sysUserRoleDao.findRoleIdsByUserId(userId);
if(roleIds==null||roleIds.size()==0)
throw new AuthorizationException();
//3.基於角色id獲取選單id(sys_role_menus)
List<Integer> menuIds=
sysRoleMenuDao.findMenuIdsByRoleIds(roleIds);
if(menuIds==null||menuIds.size()==0)
throw new AuthorizationException();
//4.基於選單id獲取許可權標識(sys_menus)
List<String> permissions=
sysMenuDao.findPermissions(menuIds);
//5.對許可權標識資訊進行封裝並返回
Set<String> set=new HashSet<>();
for(String per:permissions){
if(!StringUtils.isEmpty(per)){
set.add(per);
}
}
SimpleAuthorizationInfo info=
new SimpleAuthorizationInfo();
info.setStringPermissions(set);
return info;//返回給授權管理器
}
。。。。
}
4.4授權訪問實描述現
在需要進行授權訪問的業務層(Service)方法上,新增執行此方法需要的許可權標識,參考程式碼
@RequiresPermissions(“sys:user:update”)
說明:此要註解一定要新增到業務層方法上。
5Shiro擴充套件功能應用
5.1Shiro快取配置
當我們進行授權操作時,每次都會從資料庫查詢使用者許可權資訊,為了提高授權效能,可以將使用者許可權資訊查詢出來以後進行快取,下次授權時從快取取資料即可。
Shiro中內建快取應用實現,其步驟如下:
第一步:在SpringShiroConfig中配置快取Bean物件(Shiro框架提供)。
@Bean
public CacheManager shiroCacheManager(){
return new MemoryConstrainedCacheManager();
}
說明:這個CacheManager物件的名字不能寫cacheManager,因為spring容器中已經存在一個名字為cacheManager的物件了.
第二步:修改securityManager的配置,將快取物件注入給SecurityManager物件。
@Bean
public SecurityManager securityManager(
Realm realm,
CacheManager cacheManager) {
DefaultWebSecurityManager sManager=
new DefaultWebSecurityManager();
sManager.setRealm(realm);
sManager.setCacheManager(cacheManager);
return sManager;
}
說明:對於shiro框架而言,還可以藉助第三方的快取產品(例如redis)對使用者的許可權資訊進行cache操作.
5.2Shiro記住我
記住我功能是要在使用者登入成功以後,假如關閉瀏覽器,下次再訪問系統資源(例如首頁doIndexUI)時,無需再執行登入操作。
5.2.1客戶端業務實現
在頁面上選中記住我,然後執行提交操作,將使用者名稱,密碼,記住我對應的值提交到控制層,如圖-9所示:
圖-9
其客戶端login.html中關鍵JS實現:
function doLogin(){
var params={
username:$("#usernameId").val(),
password:$("#passwordId").val(),
isRememberMe:$("#rememberId").prop("checked"),
}
var url="user/doLogin";
console.log("params",params);
$.post(url,params,function(result){
if(result.state==1){
//跳轉到indexUI對應的頁面
location.href="doIndexUI?t="+Math.random();
}else{
$(".login-box-msg").html(result.message);
}
return false;//防止重新整理時重複提交
});
}
5.2.2服務端業務實現
服務端業務實現的具體步驟如下:
第一步:在SysUserController中的doLogin方法中基於是否選中記住我,設定token的setRememberMe方法。
@RequestMapping("doLogin")
@ResponseBody
public JsonResult doLogin(
boolean isRememberMe,
String username,
String password) {
//1.封裝使用者資訊
UsernamePasswordToken token=
new UsernamePasswordToken(username, password);
if(isRememberMe) {
token.setRememberMe(true);
}
//2.提交使用者資訊
Subject subject=SecurityUtils.getSubject();
subject.login(token);//token會提交給securityManager
return new JsonResult("login ok");
}
第二步:在SpringShiroConfig配置類中新增記住我配置,關鍵程式碼如下:
@Bean
public RememberMeManager rememberMeManager() {
CookieRememberMeManager cManager=
new CookieRememberMeManager();
SimpleCookie cookie=new SimpleCookie("rememberMe");
cookie.setMaxAge(7*24*60*60);
cManager.setCookie(cookie);
return cManager;
}
第三步:在SpringShiroConfig中修改securityManager的配置,為
securityManager注入rememberManager物件。參考黃色部分程式碼。
@Bean
public SecurityManager securityManager(
Realm realm,CacheManager cacheManager
RememberMeManager rememberManager) {
DefaultWebSecurityManager sManager=
new DefaultWebSecurityManager();
sManager.setRealm(realm);
sManager.setCacheManager(cacheManager);
sManager.setRememberMeManager(rememberManager);
return sManager;
}
第四步:修改shiro的過濾認證級別,將/=author修改為/=user,檢視黃色背景部分。
@Bean
public ShiroFilterFactoryBean shiroFilterFactory(
SecurityManager securityManager) {
ShiroFilterFactoryBean sfBean=
new ShiroFilterFactoryBean();
sfBean.setSecurityManager(securityManager);
//假如沒有認證請求先訪問此認證的url
sfBean.setLoginUrl("/doLoginUI");
//定義map指定請求過濾規則(哪些資源允許匿名訪問,哪些必須認證訪問)
LinkedHashMap<String,String> map=
new LinkedHashMap<>();
//靜態資源允許匿名訪問:"anon"
map.put("/bower_components/**","anon");
map.put("/build/**","anon");
map.put("/dist/**","anon");
map.put("/plugins/**","anon");
map.put("/user/doLogin","anon");
map.put("/doLogout", "logout");//自動查LoginUrl
//除了匿名訪問的資源,其它都要認證("authc")後訪問
map.put("/**","user");//authc
sfBean.setFilterChainDefinitionMap(map);
return sfBean;
}
說明:檢視瀏覽器cookie設定,可在瀏覽器中輸入如下語句。
chrome://settings/content/cookies
5.3Shiro會話管理配置
使用shiro框架實現認證操作,使用者登入成功會將使用者資訊寫入到會話物件中,其預設時長為30分鐘,假如需要對此進行配置,可參考如下配置:
第一步:在SpringShiroConfig類中,新增會話管理器配置。關鍵程式碼如下:
@Bean
public SessionManager sessionManager() {
DefaultWebSessionManager sManager=
new DefaultWebSessionManager();
sManager.setGlobalSessionTimeout(60*60*1000);
return sManager;
}
第二步:在SpringShiroConfig配置類中,對安全管理器 securityManager 增加 sessionManager值的注入,關鍵程式碼如下:
@Bean
public SecurityManager securityManager(
Realm realm,CacheManager cacheManager,
RememberMeManager rememberManager,
SessionManager sessionManager) {
DefaultWebSecurityManager sManager=
new DefaultWebSecurityManager();
sManager.setRealm(realm);
sManager.setCacheManager(cacheManager);
sManager.setRememberMeManager(rememberMeManager);
sManager.setSessionManager(sessionManager);
return sManager;
}
課堂練習:
1.獲取使用者登陸資訊,並將登陸使用者名稱呈現在系統主頁(starter.html)上.
第一步:定義一個工具類(ShiroUtils),獲取使用者登陸資訊.
package com.cy.pj.common.util;
import org.apache.shiro.SecurityUtils;
import com.cy.pj.sys.entity.SysUser;
public class ShiroUtils {
public static String getUsername() {
return getUser().getUsername();
}
public static SysUser getUser() {
return (SysUser)
SecurityUtils.getSubject().getPrincipal();
}
}
第二步:修改PageController中的doIndexUI方法,程式碼如下:
@RequestMapping("doIndexUI")
public String doIndexUI(Model model) {
SysUser user=ShiroUtils.getUser();
model.addAttribute("user",user);
return "starter";
}
第三步:藉助thymeleaf中的表示式直接在頁面上(starter.html)獲取登陸使用者資訊
<span class="hidden-xs" id="loginUserId">[[${user.username}]]</span>
2.修改登陸使用者的密碼?(參考使用者模組文件)
分析:
1)確定都要修改誰?(密碼,鹽值,修改時間)
2)服務端的設計實現?(dao,service,controller)
3)客戶端的設計實現?(非同步提交使用者密碼資訊)
6Shiro總結
6.1重點和難點分析
1.shiro 認證過程分析及實現(判定使用者身份的合法性)。
2.Shiro 授權過程分析及實現(對資源訪問進行許可權檢測和授權)。
3.Shiro 快取,會話時長,記住我等功能實現。
6.2常見FAQ
1.說說shiro的核心元件?
2.說說shiro的認證流程,你如何知道的,為什麼要認證?
3.說說shiro的授權流程,你如何知道流程是這樣的,為什麼要進行授權?
4.Shiro中內建快取應用實現?為什麼使用此快取?是否可以使用第三方快取?
5.Shiro中的記住我功能如何實現?為什麼要使用這個功能?
6.Shiro中會話session的預設時長是多少,你怎麼知道的?
6.3Bug分析
1.SecurityManager包名錯誤。
2.MD5加密演算法設定錯誤。
3.Realm物件沒有交給spring管理
4.使用者名稱和密碼接收錯誤
5.CacheManager名字與Spring中內建的CacheManager名字衝突。
6.過濾規則配置錯誤?
7…
相關文章
- Booking:2023年印度遊客和旅遊生態系統報告
- 旅遊/理途旅遊系統開發技術/原始碼/理途旅遊程式設計原始碼程式設計
- 初入Hadoop生態系統Hadoop
- Laravel生態系統中EcosystemLaravel
- 二代旅遊網站程式,旅遊網站CMS,旅遊網站目的地管理系統網站
- GroupM:2020年移動營銷生態系統報告
- SuperAwesome:兒童遊戲生態系統是如何改變的遊戲
- 理途旅遊系統技術開發/理途旅遊開發原理/理途旅遊NFT元宇宙元宇宙
- JVM生態系統報告2018JVM
- 2018 JVM生態系統報告JVM
- 作業系統:計算機的生態系統作業系統計算機
- 德勤&MITSloan報告:協同勞動力生態系統MIT
- 建立一個受動漫啟發的NFT生態系統
- 豐富的包(packages)生態系統Package
- Laravel 生態系統Forge Vapor Nova EnvoyerLaravelVapor
- Rust 生態系統的非官方指南Rust
- 動態系統 MATLAB 例子Matlab
- Sensor Tower:2021年移動應用生態系統使用報告
- 理途旅遊/系統技術開發原理/理途旅遊原始碼開發示例原始碼
- islandswap生態多元化NFT鏈遊系統開發模式詳解模式
- NFT理途旅遊開發原始碼/理途旅遊系統原始碼開發/理途旅遊技術開發原理原始碼
- 印度旅遊部:2019年印度旅遊統計資料
- 國產作業系統的生態之路作業系統
- EOS生態系統技術開發搭建
- 深度探索MMO生態構建——社交系統
- 2021年JVM生態系統報告 - snykJVM
- 中興&Omdia:5G訊息推動生態系統創新
- 基於kubernetes雲作業系統的生態系統 - Kelsey Hightower作業系統
- 世界旅遊組織報告:旅遊業氣候行動
- 途牛旅遊系統架構的優化實踐架構優化
- 2017年旅遊報告:移動科技改造旅遊行業行業
- .NET 生態系統的蛻變之 .NET 6
- **Linux 配置系統網路(動態)**Linux
- Llama 3.2 Vision & Molmo:多模態開源生態系統基礎
- 雪亮工程動態視訊監控系統建設動態人臉識別系統搭建
- 理途旅遊零擼系統開發邏輯/理途旅遊開發功能/python技術語言Python
- 紅蟻旅遊(分紅)系統開發技術(詳情)
- 紅蟻旅遊商城系統技術開發(詳情分析)