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年印度遊客和旅遊生態系統報告
- 旅遊/理途旅遊系統開發技術/原始碼/理途旅遊程式設計原始碼程式設計
- 二代旅遊網站程式,旅遊網站CMS,旅遊網站目的地管理系統網站
- 理途旅遊系統技術開發/理途旅遊開發原理/理途旅遊NFT元宇宙元宇宙
- Javaweb實現旅遊管理系統(商城)(二)JavaWeb
- NFT理途旅遊開發原始碼/理途旅遊系統原始碼開發/理途旅遊技術開發原理原始碼
- 理途旅遊/系統技術開發原理/理途旅遊原始碼開發示例原始碼
- NoSQL生態系統SQL
- 社會化旅遊對比傳統旅遊–資料資訊圖
- 印度旅遊部:2019年印度旅遊統計資料
- Hadoop 生態系統Hadoop
- hadoop生態系統Hadoop
- 【轉】Nosql生態系統SQL
- islandswap生態多元化NFT鏈遊系統開發模式詳解模式
- 2017年旅遊報告:移動科技改造旅遊行業行業
- 夜間旅遊有效促進旅遊產業升級,推動全國夜遊經濟發展產業
- 途牛旅遊系統架構的優化實踐架構優化
- 美國移動廣告生態系統圖譜–資訊圖
- 理途旅遊零擼系統開發邏輯/理途旅遊開發功能/python技術語言Python
- 理途旅遊系統開發技術原理丨原始碼丨理途旅遊程式設計程式碼示例原始碼程式設計
- 雲端計算生態系統
- 集團資訊生態系統
- 產品的生態系統
- 紅蟻旅遊(分紅)系統開發技術(詳情)
- 紅蟻旅遊商城系統技術開發(詳情分析)
- 如何優化移動旅遊體驗?優化
- 日本旅遊產業——誰在選擇跟團旅遊?產業
- 旅遊景區IP網路廣播系統方案-旅遊風景區景點IP網路廣播建設指南
- 移動5年 Android生態系統的演進Android
- 旅遊網站網站
- 初入Hadoop生態系統Hadoop
- Hadoop工具生態系統指南Hadoop
- Hadoop生態系統介紹Hadoop
- 圖解:RTB廣告生態系統圖解
- 優酷旅遊、新浪旅遊釋出八大榜單
- 作業系統:計算機的生態系統作業系統計算機
- 文旅夜遊如何實現多業態驅動不斷優化升級優化
- 建立一個受動漫啟發的NFT生態系統