国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Shiro安全框架簡介

這篇具有很好參考價值的文章主要介紹了Shiro安全框架簡介。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

?一、權限管理

1.1 什么是權限管理

  • 基本上只要涉及到用戶參數的系統(tǒng)都要進行權限管理,使用權限管理實現了對用戶訪問系統(tǒng)的控制,不同的用戶訪問不同的資源。按照安全規(guī)則或者安全策略控制用戶訪問資源,而且只能訪問被授權的資源
  • 權限管理包括認證和授權兩部分,當用戶訪問資源時先對其進行身份的認證,認證通過后即可訪問已經授權的資源。

1.2 身份認證

  • 用來判斷一個用戶是否合法的處理過程。用過用戶輸入的用戶名或者口令來和系統(tǒng)中存儲進行比較,從而認證用戶的身份是否正確

對于身份認證,也就是之前做的的登錄

1.3 授權

  • 用來控制認證過后的用戶可以訪問哪些資源。用戶身份認證后需要給該用戶分配可訪問的資源,如果沒有某個資源的權限,那么將無法訪問

二、Shiro架構

2.1 Shiro的理解

是一個功能強大且易實現的Java安全框架,使用Shiro可以執(zhí)行認證、授權、加密和會話管理。使用Shiro中提供的API可以快速輕松的保護任何程序

Shiro不依賴于WEB,即使是一個測試程序也能夠使用Shiro中的功能

2.2 Shiro的體系

官方圖示:Shiro安全框架簡介

原理:

Shiro安全框架簡介

Subject

  • 表示主體,外部應用和Subject進行交互。Subject中記錄了當前操作用戶,這個用戶可以是一個發(fā)送請求的用戶,也可以是一個運行的程序
  • Subject在Shiro是一個接口,定義了很多認證授權的相關方法,外部程序通過Subject進行認證授權,Subject又是通過SecurityManager安全管理器就行認證管理

SecurityManager

  • 表示安全管理器,是Shiro中的核心,用來協調其托管的組件,以保證它們能夠順利協同工作。
  • 可以進行會話管理等

Authenticator

  • 表示身份認證器,負責執(zhí)行和響應用戶的身份認證嘗試的組件。當用戶進行登錄操作時,此組件進行處理

Authorizer

  • 表示授權器,負責控制用戶在系統(tǒng)中可以訪問哪些資源。在訪問資源時都需要該組件進行判斷當前用戶是否擁有這個資源的權限

Realm

  • 表示領域,充當Shiro與應用程序的安全數據之間的橋梁或者連接器,和DataSource數據源差不多,當需要和安全相關的數據(如用戶賬號)進行實際交互從而執(zhí)行認證和授權時,Shiro會從應用配置的一個或者多個Realm中查詢其中的內容
  • SecurityManager進行安全認證時需要通過Realm獲取到用戶權限數據
  • Realm不只是從數據庫取數據,還有認證和授權的相關邏輯代碼

SessionManager

  • 表示會話管理,知道如果創(chuàng)建和管理用戶生命周期,以便為所欲環(huán)境中的用戶提供強大的會話體驗
  • 不依賴WEB容器,所以Shiro可以使用在非WEB應用中也可以將分布式應用的會話集中在一點管理,次特征可以使它實現單點登錄

SessionDao

  • 表示會話Dao,是對session會話操作的一套接口

CacheManager

  • 表示緩存管理器,將用戶權限存儲到緩存中,從而提高性能

Cryptography

  • 表示密碼管理,Shiro中提供了一套加密/解密的組件,方便開發(fā)

三、Shiro中的認證

3.1 認證中的關鍵對象

  • Subject:主體

訪問系統(tǒng)的每一個用戶或者應用程序,經過認證的都成為主體

  • Principal:身份信息

是主體(Subject)進行身份證認證的表示,表示必須具有唯一性。比如用戶名/手機號/郵箱,一個主體(Subject)中可以有多個身份信息,但必須有一個主身份

  • Credential:憑證信息

3.2 認證流程

圖示:

Shiro安全框架簡介

文字:

  1. 收集使用者的Principal和Credential
  1. 提交進行身份驗證
  1. 如果驗證成功就允許訪問,否則重試身份證驗證或者阻止訪問

3.3 環(huán)境搭建

  1. 引入Shiro依賴
<dependency>
????<groupId>org.apache.shiro</groupId>
????<artifactId>shiro-core</artifactId>
????<version>1.9.1</version>
</dependency>
  1. 在resources下創(chuàng)建.ini的配置文件,來臨時模擬數據庫存儲用戶的身份信息和憑證信息

Shiro安全框架簡介

[users]
admin=1234
tom=222
jack=456
  1. 編寫認證代碼
public class ShiroAuthentication {
????public static void main(String[] args) {
????????// 1.創(chuàng)建SecurityManager安全管理器的實現類
????????DefaultSecurityManager securityManager = new DefaultSecurityManager();

????????// 2.將Realm中的數據設置到安全管理器中
????????securityManager.setRealm(new IniRealm("classpath:shiro.ini")); // Realm去讀取ini中的主體與憑證信息

????????// 3.將安全管理器設置到全局安全工具類中
????????SecurityUtils.setSecurityManager(securityManager);

????????// 4.獲取主體
????????Subject subject = SecurityUtils.getSubject();

????????// 5.認證
????????if (!subject.isAuthenticated()) { // 是否已經認證
????????????// 如果沒有認證過,那么證明該用戶第一次登錄.收集使用者的身份信息和憑證信息
????????????UsernamePasswordToken token = new UsernamePasswordToken("admin","1234"); // 模擬前臺輸入
????????????// 提交身份信息和憑證信息
????????????subject.login(token);
????????}
????}
}

3.4 處理結果

如果提交成功,執(zhí)行后續(xù)的邏輯代碼;提交過程中出現錯誤,那么Shiro將以拋異常的形式聲明錯誤

異常列表:

  • UnknowAccountException ?--> 未知賬號異?!居脩裘e誤】
  • IncorrectCredentialsException ?--> 憑證信息異?!久艽a錯誤】
  • LockedAccountException ?--> 鎖定賬號異常
  • ExcessiveAttemptsException ?--> 過度嘗試異常
  • AuthenticationException ?--> 身份認證異常

修改以上程序:

try {
????// 開始認證
????subject.login(token);
}catch (UnknownAccountException e){
????System.out.println("賬號錯誤");
}catch (IncorrectCredentialsException e){
????System.out.println("密碼錯誤");
}

3.5 獲取主體身份信息與注銷

此操作必須保證認證通過

  • 獲取主體身份信息
if (subject.isAuthenticated()){ // 認證通過
????Object principal = subject.getPrincipal(); // 6. 獲取身份信息
????System.out.println(principal); // admin
}
  • 注銷
subject.logout();

3.6 底層實現

身份信息校驗

  • 在SimpleAccountRealm類中的doGetAuthenticationInfo方法判斷身份信息是否一致
  • 如果用戶名錯誤,那么返回的info==null,系統(tǒng)拋出UnknowAccountException異常

Shiro安全框架簡介

Shiro安全框架簡介

密碼校驗

  • 在AuthenticatingRealm類中的assertCredentialsMatch方法進行密碼(憑證信息)的校驗,Shiro中憑證信息默認的校驗規(guī)則是equals
  • 如果密碼錯誤,拋出IncorrectCredentialsException異常

Shiro安全框架簡介

Shiro安全框架簡介

3.7 自定義Realm

以后校驗用戶名肯定不能使用Shiro中定義的,需要連接數據庫,通過用戶名查詢。所以Shiro中也可以讓我們自定義Realm

Realm繼承圖

全部

Shiro安全框架簡介

主要部分

Shiro安全框架簡介

認證方法和授權方法都在AuthorizingRealm定義為抽象方法,等待子類繼承并重寫這兩個方法。

SimpleAccountRealm繼承了AuthorizingRealm,所以這個類里面有認證和授權功能,其兩個功能對應的方法為:

  • doGetAuthenticationInfo:認證
  • doGetAuthorizationInfo:授權

以后自定義的Realm只需要繼承AuthorizingRealm,然后重寫這兩個方法

/**
* 自定義Realm,繼承AuthorizingRealm類
*/
public class LoginRealm extends AuthorizingRealm {
????/*
???? 授權
????*/
????@Override
????protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
????????return null;
????}

????/*
???? 認證
????*/
????@Override
????protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
????????return null;
????}
}

在doGetAuthenticationInfo方法中獲取用戶的身份信息,然后校驗是否和數據庫中的一致

@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
????// getPrincipal()獲取身份信息
????String username = (String) token.getPrincipal();
????if ("admin".equals(username)){
????????// 正確 返回AuthenticationInfo的實現類
????????// 參數:1.當前用戶的身份信息 2.驗證主體的憑證信息[如果和前臺傳入的不一致,拋出IncorrectCredentialsException異常] 3.當前Realm
????????return new SimpleAuthenticationInfo(username,"1234",super.getName());
????}
????// 不正確返回一個null, info == null 拋出UnknownAccountException異常
????return null;
}

3.8 加密

測試程序:

public class MD5Test {
????public static void main(String[] args) {
????????// 加密
????????Md5Hash md5Hash = new Md5Hash("1234");

????????// 加密+salt(鹽)
????????Md5Hash md5Hash1 = new Md5Hash("1234", "f5gy");

????????// 加密+salt(鹽)+散列次數
????????Md5Hash md5Hash2 = new Md5Hash("1234","f5gy",1024);
????}
}

整合認證:

  1. 修改認證方法
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
????// getPrincipal()獲取身份信息
????String username = (String) token.getPrincipal();
????if ("admin".equals(username)){
????????// 正確 返回AuthenticationInfo的實現類
????????/*
????????參數:
????????????1.當前用戶的身份信息
????????????2.驗證主體的憑證信息[如果和前臺傳入的不一致,拋出IncorrectCredentialsException異常]
????????????3.鹽
????????????4.當前Realm
????????*/
????????String password = "75b323294effa42ed07f895f37f9a192";
????????String salt = "f5gy";
????????return new SimpleAuthenticationInfo(username,password, ByteSource.Util.bytes(salt),super.getName());
????}
????// 不正確返回一個null, info == null 拋出UnknownAccountException異常
????return null;
}
  1. 修改密碼比較器

Shiro默認實用的是simpleCredentialsMatcher中的doCredentialsMatcher方法,這個方法使用的是equals的方式進行比較密碼。

CredentialsMatcher繼承圖:

Shiro安全框架簡介

使用HashedCredentialsMatcher這個類

LoginRealm realm = new LoginRealm();
HashedCredentialsMatcher hash = new HashedCredentialsMatcher();
// 設置算法
hash.setHashAlgorithmName("MD5");
// 設置散列次數
hash.setHashIterations(1024);
// 設置到Realm中
realm.setCredentialsMatcher(hash);

四、Shiro中的授權

4.1 授權中的關鍵對象

  • Who

表示主體,主題需要系統(tǒng)中的資源

  • What

表示資源,這個資源可以是一個按鈕、菜單等。資源又分為資源實例和資源類型

  • How

表示權限/許可,控制主體對資源的訪問

4.2 授權方式

  • 基于角色的訪問控制(Role-Based Access Control):以角色為中心進行權限控制
  • 基于資源的訪問控制(Resource-Based Access Control):以資源為中心進行權限控制

4.3 權限字符串

權限字符串的規(guī)則:資源標識符:操作,意思是對哪個資源進行哪些操作。":"是分割符,權限字符串可以使用"*"來表示通配符

4.4 校驗角色

  1. 在doGetAuthorizationInfo方法中設置當前主體的角色
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
????// 獲取主題中的身份信息[用戶名]
????String principal = (String) principals.getPrimaryPrincipal();
????// 返回AuthorizationInfo的實現類
????SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
????// 給當前主體添加角色
????info.addRole("admin");
????info.addRole("user");
????return info;
}
  1. 模擬前臺測試
if (subject.isAuthenticated()){
????// 校驗單個角色
????System.out.println(subject.hasRole("admin")); // 是否有admin角色
????// 校驗多個角色
????System.out.println(subject.hasAllRoles(Arrays.asList("admin", "user"))); // 是否同時有admin user角色
????// 校驗 多次 角色
????boolean[] booleans = subject.hasRoles(Arrays.asList("admin", "user", "super"));
????for (boolean b : booleans) {
????????System.out.println(b);
????}
}

4.5 校驗權限字符串

  1. 在doGetAuthorizationInfo方法中設置當前主體的權限字符串
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
????// 獲取主題中的身份信息[用戶名]
????String principal = (String) principals.getPrimaryPrincipal();
????// 返回AuthorizationInfo的實現類
????SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
????// 給當前主體添加權限字符串
????info.addStringPermission("user:update");
????info.addStringPermission("product:select");
????return info;
}
  1. 模擬前臺測試

五、整合SpringBoot

5.1 整合思路

Shiro安全框架簡介

5.2 環(huán)境搭建

  1. 導入springboot和shiro整合的依賴包
<dependency>
????<groupId>org.apache.shiro</groupId>
????<artifactId>shiro-spring-boot-starter</artifactId>
????<version>1.4.0</version>
</dependency>
  1. 創(chuàng)建一個類,繼承AuthorizingRealm類,重寫授權和認證方法
public class MyRealm extends AuthorizingRealm {
????@Override
????protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
????????return null;
????}

????@Override
????protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
????????return null;
????}
}
  1. 編寫shiro和springboot整合的配置
@Configuration
public class ShiroConfig {
????@Bean
????public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager defaultWebSecurityManager){
????????ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
????????// 將SecurityManager設置到Filter中
????????shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
????????return shiroFilterFactoryBean;
????}
????@Bean
????public DefaultWebSecurityManager defaultWebSecurityManager(Realm realm){
????????DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
????????// 給安全管理器設置Realm
????????defaultWebSecurityManager.setRealm(realm);
????????return defaultWebSecurityManager;
????}
????@Bean
????public Realm Realm(){
????????LoginRealm loginRealm = new LoginRealm();
????????return loginRealm;
????}
}
  1. 在ShiroFilter過濾器中配置需要攔截的資源URL
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager defaultWebSecurityManager){
????ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
????// 將SecurityManager設置到Filter中
????shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
????
????//設置受限資源
????Map<String,String> map = new HashMap<>();
????/**
????* authc:該路徑資源需要認證和授權
????*/
????map.put("/**","authc"); // "/**"代表所有的資源路徑都攔截
????shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
????return shiroFilterFactoryBean;
}
  1. 訪問資源跳轉到login.jsp,修改默認跳轉路徑
shiroFilterFactoryBean.setLoginUrl("/doLogin");

@Controller
public class IndexController {

????@GetMapping("/doLogin")
????public String doLogin(){
????????return "login";
????}
}
  1. 攔截后訪問/doLogin路徑

Shiro安全框架簡介

5.3 ShiroFilter過濾列表

Shiro中提供了多個默認的過濾器,用這些過濾器來控制指定URL路徑下的資源

配置縮寫

對應過濾器

描述

anon

AnonymousFilter

指定URL路徑下的資源可以匿名訪問

authc

FormAuthenticationFilter

指定URL路徑下的資源需要認證過后才能訪問

authcBasic

BasicHttpAuthenticationFilter

指定URL路徑下的資源需要basic登錄

logout

LogoutFilter

注銷過濾器,只需配置對應的URL路徑即可實現

noSessionCreation

NoSessionCreationFilter

禁止創(chuàng)建Session會話

perms

PermissionsAuthorizationFilter

需要有該URL資源對應的權限字符串才能訪問

port

PortFilter

指定某個端口可以訪問

rest

HttpMethodPermissionFilter

將HTTP請求轉換成相對應的動詞來構建權限字符串

roles

RolesAuthorizationFilter

需要有指定角色才能訪問

ssl

SslFilter

需要https請求才能訪問

user

UserFilter

需要已登錄或者"記住我"的用戶才能訪問

六、連接數據庫完成認證

6.1 注冊

  1. 表設計

Shiro安全框架簡介

  1. 注冊頁面
<!DOCTYPE html>
<html lang="en">
??<head>
????<meta charset="UTF-8">
????<title>Title</title>
??</head>
??<body>
????<h1>注冊頁面</h1>
????<hr>
????<form action="/user/register" method="post">
??????用戶名 : <input type="text" name="username"><br>
??????密碼 : <input type="password" name="password"> <br>
???????<input type="submit" value="注冊">
????</form>
??</body>
</html>
  1. 實體類POJO
@Data
public class User {
????private Long id;
????private String username;
????private String password;
????private String salt;
}
  1. 編寫Controller,調用service處理業(yè)務邏輯
@Controller
@RequestMapping("/user")
public class UserController {
????
????@Autowired
????private UserService userService;

????@GetMapping("/doRegister")
????public String doRegister(){
????????return "register";
????}
????
????@PostMapping("/register")
????public String register(User user){
????int count = userService.register(user);
????????if (count > 0)
????????????return "redirect:/doLogin";
????????else
????????????return "redirect:/doRegister";
????}
}
  1. 在ShiroFilter放過這些URL路徑
map.put("/user/register","anon");
map.put("/user/doRegister","anon");
  1. service中完成加密和散列鹽,調用Mapper完成注冊
@Service
public class UserServiceImpl implements UserService {

????@Autowired
????private UserMapper userMapper;

????@Override
????public int register(User user) {
????????String salt = "ga*n";
????????Md5Hash md5Hash = new Md5Hash(user.getPassword(),salt,1024);
????????user.setPassword(md5Hash.toHex());
????????user.setSalt(salt);
????????return userMapper.insert(user);
????}
}
  1. Mapper接口和SQL語句
public interface UserMapper {

????int insert(User user);
}
<mapper namespace="com.jiuxiao.mapper.UserMapper">

??<insert id="insert">
????insert into t_user(id,username,password,salt) values(null,#{username},#{password},#{salt})
??</insert>
</mapper>
  1. 啟動類上添加@MapperScan注解,掃描Mapper包
@SpringBootApplication
@MapperScan("com.jiuxiao.mapper")
public class ShiroApp {
????public static void main(String[] args) {
????????SpringApplication.run(ShiroApp.class,args);
????}
}
  1. 注冊頁面輸入用戶信息后,完成注冊
  2. Shiro安全框架簡介

6.2 認證

  1. 在Shiro配置中修改密碼比較器
@Bean
public Realm realm(){
????LoginRealm loginRealm = new LoginRealm();
????HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
????matcher.setHashAlgorithmName("MD5");
????matcher.setHashIterations(1024);
????loginRealm.setCredentialsMatcher(matcher);
????return loginRealm;
}
  1. 在自定義的Realm的doGetAuthenticationInfo方法中編寫認證邏輯
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
????
????@Autowired
????private UserService userService;
????
????// 獲取主體中的身份信息
????String principal = (String) authenticationToken.getPrincipal();
????// 調用service查詢數據庫
????User user = userService.selectByUsername(principal);
????if (!ObjectUtils.isEmpty(user)){
??????? // 如果可以查詢到,校驗密碼
????????return new SimpleAuthenticationInfo(user.getUsername(),user.getPassword(), ByteSource.Util.bytes(user.getSalt()),super.getName());
????}
????// 查詢不到直接返回null
????return null;
}
  1. service調用Mapper
@Override
public User selectByUsername(String principal) {
????return userMapper.selectByUsername(principal);
}
  1. Mapper接口與SQL語句
User selectByUsername(String principal);
<select id="selectByUsername" resultType="com.jiuxiao.pojo.User">
?? select * from t_user where username = #{username}
</select>
  1. 登錄頁面代碼
<!DOCTYPE html>
<html lang="en">
??<head>
????<meta charset="UTF-8">
????<title>$Title$</title>
??</head>
??<body>
????<h1>登錄頁面</h1>
????<hr>
????<form action="/user/login" method="post">
??????用戶名: <input type="text" name="username"> <br>
??????密碼: <input type="password" name="password"> <br>
??????<input type="submit" value="登錄">
????</form>
??</body>
</html>
  1. 在Controller中編寫對應URL,封裝token,并處理異常結果
@Controller
@RequestMapping("/user")
public class UserController {

????@PostMapping("/login")
????public String login(String username,String password){
????????Subject subject = SecurityUtils.getSubject();
????????UsernamePasswordToken token = new UsernamePasswordToken(username, password);
????????try {
????????????subject.login(token);
????????????return "index"; // 登陸成功跳轉到首頁
????????} catch (UnknownAccountException e) {
????????????e.printStackTrace();
????????????System.out.println("用戶名錯誤");
????????}catch (IncorrectCredentialsException e){
????????????e.printStackTrace();
????????????System.out.println("密碼錯誤");
????????}
????????return "login"; // 登錄失敗跳轉到登錄頁面
????}
}
  1. 首頁代碼
<!DOCTYPE html>
<html lang="en">
<head>
??<meta charset="UTF-8">
??<title>$Title$</title>
</head>
<body>
??<h1>首頁</h1>
??<hr>
??<ul>
????<li><a href="">用戶管理</a></li>
????<li><a href="">商品管理</a></li>
????<li><a href="">菜單管理</a></li>
????<li><a href="">物流管理</a></li>
??</ul>
</body>
</html>
  1. 在ShiroFilter過濾器中放過登錄URL
map.put("/user/login","anon");
  1. 頁面登錄成功后,進入到index.html

Shiro安全框架簡介

6.3 注銷

① 配置方式

  1. 在ShiroFilter過濾器中添加注銷的URL
map.put("/user/logout","logout");
  1. 在頁面直接輸入這個URL即可注銷

② 代碼方式

調用subject的logout方法完成注銷,頁面訪問該Controller的URL

七、授權的基本使用

7.1 校驗角色

在自定義的Realm的doGetAuthorizationInfo方法中給當前主體賦予角色

@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
????// 獲取主體中的身份信息
????String principal = (String) principalCollection.getPrimaryPrincipal();
????if ("jiuxiao".equals(principal)){ // 給jiuxiao用戶賦予admin和user角色
????????SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
????????// 增加admin和user角色
????????simpleAuthorizationInfo.addRole("admin");
????????simpleAuthorizationInfo.addRole("user");
????????return simpleAuthorizationInfo;
????}
????return null;
}

① 編碼方式

單個角色:使用subject中的hasRole方法

@Controller
@RequestMapping("/user")
public class UserController {
????
????@GetMapping("/save")
????@ResponseBody
????public String save(){
????????Subject subject = SecurityUtils.getSubject();
????????if (!subject.hasRole("admin")) { // 校驗當前角色是否有admin這個角色
????????????return "權限不足";
????????}else{
????????? return "訪問成功"; ??
????????}
????}
}

多個角色:使用subject中的hasAllRoles方法【這些角色都有才能訪問】

@Controller
@RequestMapping("/user")
public class UserController {
????
????@GetMapping("/save")
????@ResponseBody
????public String save(){
????????List<String> roles = Arrays.asList("admin", "user");
????????if (SecurityUtils.getSubject().hasAllRoles(roles)) {
????????????return "訪問成功";
????????}else{
????????????return "權限不足";
????????}
????}
}

② 注解方式

單個角色:直接在注解參數中寫入對應的角色即可

@Controller
@RequestMapping("/user")
public class UserController {
????
????@GetMapping("/save")
????@ResponseBody
????@RequiresRoles("admin")
????public String save(){
????????return "訪問成功";
????}
}

多個角色:在注解中以數組的形式寫入多個角色【這些角色都有才能訪問】

@GetMapping("/save")
@ResponseBody
@RequiresRoles(value = {"admin","user"})
public String save(){
????return "訪問成功";
}

7.2 校驗權限字符串

在自定義的Realm的doGetAuthorizationInfo方法中給當前主體賦予權限字符串

@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
????String principal = (String) principalCollection.getPrimaryPrincipal();
????System.out.println("執(zhí)行授權:"+principal);
????if ("jiuxiao".equals(principal)){
????????SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
????????// 添加權限字符串
????????simpleAuthorizationInfo.addStringPermission("user:update");
????????simpleAuthorizationInfo.addStringPermission("product:create");
????????return simpleAuthorizationInfo;
????}
????return null;
}

① 編碼方式

調用subject中的isPermittedAll方法,參數為可變長參數(可以傳一個或者多個)【如果是多個,那么這個主體需要擁有參數里面所有的權限字符串才能訪問】

@Controller
@RequestMapping("/user")
public class UserController {
????
????@GetMapping("/save")
????@ResponseBody
????public String save(){
????????Subject subject = SecurityUtils.getSubject();
????????// if (subject.isPermittedAll("user:update")){ // 判斷當前主體使用擁有對user資源的001實例的更新操作
????????if (subject.isPermittedAll("user:update","product:update")){
????????????return "訪問成功";
????????}else{
????????????return "權限不足";
????????}
????}
}

② 注解方式

單個權限字符串:直接在注解參數中寫入需要校驗的權限字符串即可

@GetMapping("/save")
@ResponseBody
@RequiresPermissions("user:update")
public String save(){
????return "訪問成功";
}

多個權限字符串:在注解中以數組的形式寫入多個權限字符串【當前主體主要擁有這些權限字符串才能訪問】

@GetMapping("/save")
@ResponseBody
@RequiresPermissions(value = {"user:update","product:create"})
public String save(){
????return "訪問成功";
}

③ 配置方式

在ShiroFilter過濾器使用perms進行權限的校驗

map.put("/user/save","perms[user:update,product:delete]"); // 數組中添加權限字符串

如果權限不足,頁面拋出401錯誤

在ShiroFilter中定義權限不足后跳轉的URL

注意:定義權限不足跳轉URL的方式只限制配置方式,別的方式都不能使用,權限不足時會拋出AuthorizationException異常

八、連接數據庫完成授權

8.1 表設計:

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for role_perms
-- ----------------------------
DROP TABLE IF EXISTS `role_perms`;
CREATE TABLE `role_perms` ?(
??`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主鍵',
??`roleid` int(11) NULL DEFAULT NULL COMMENT '角色id',
??`permid` int(11) NULL DEFAULT NULL COMMENT '權限id',
??PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_croatian_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Table structure for role_user
-- ----------------------------
DROP TABLE IF EXISTS `role_user`;
CREATE TABLE `role_user` ?(
??`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主鍵',
??`roleid` int(11) NULL DEFAULT NULL COMMENT '角色id',
??`userid` int(11) NULL DEFAULT NULL COMMENT '用戶id',
??PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_croatian_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Table structure for t_perms
-- ----------------------------
DROP TABLE IF EXISTS `t_perms`;
CREATE TABLE `t_perms` ?(
??`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主鍵',
??`perm` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_croatian_ci NULL DEFAULT NULL COMMENT '權限字符串',
??`url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_croatian_ci NULL DEFAULT NULL COMMENT '資源URL',
??PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_croatian_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Table structure for t_role
-- ----------------------------
DROP TABLE IF EXISTS `t_role`;
CREATE TABLE `t_role` ?(
??`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主鍵',
??`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_croatian_ci NULL DEFAULT NULL COMMENT '角色',
??PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_croatian_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Table structure for t_user
-- ----------------------------
DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` ?(
??`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主鍵',
??`username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_croatian_ci NULL DEFAULT NULL COMMENT '用戶名(身份信息)',
??`password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_croatian_ci NULL DEFAULT NULL COMMENT '密碼(憑證信息)',
??`salt` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_croatian_ci NULL DEFAULT NULL COMMENT '鹽',
??PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_croatian_ci ROW_FORMAT = Dynamic;

SET FOREIGN_KEY_CHECKS = 1;

8.2 POJO

User

@Data
public class User {
????private Long id;
????private String username;
????private String password;
????private String salt;
????private List<Role> roles;
}

Role

@Data
public class Role {
????private Integer id;
????private String name;
????private List<Perms> perms;
}

Perms文章來源地址http://www.zghlxwxcb.cn/news/detail-419135.html

@Data
public class Perms {
????private Integer id;
????private String perm;
????private String url;
}

8.3 授權角色

  1. Mapper接口與SQL語句
List<Role> selectRoleNameByUserId(String username);
<select id="selectRoleNameByUserId" resultType="com.jiuxiao.pojo.Role">
????select r.id,r.name
????from t_user u
????left join role_user ru on ru.userid = u.id
????left join t_role r on r.id = ru.roleid
????where u.username = #{username}
</select>
  1. Service
@Override
public List<Role> getRoleNameByUsername(String username) {
????return userMapper.selectRoleNameByUsername(username);
}
  1. 自定義Realm中進行授權
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
????String principal = (String) principalCollection.getPrimaryPrincipal();
????List<Role> roles = userService.getRoleNameByUsername(principal);
????if(!CollectionUtils.isEmpty(roles)){
????????SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
????????roles.forEach(role-> simpleAuthorizationInfo.addRole(role.getName()));
????????return simpleAuthorizationInfo;
????}
????return null;
}

8.4 授權字符串

  1. Mapper接口與SQL語句
?List<String> selectPermByRoleId(Integer id);
<select id="selectPermByRoleId" resultType="string">
????select p.perm
????from t_role r
????left join role_perms rp on r.id = rp.roleid
????left join t_perms p on rp.permid = p.id
????where r.id = #{id}
</select>
  1. Service
@Override
public List<String> getPermByRoleId(Integer id) {
????return userMapper.selectPermByRoleId(id);
}
  1. 自定義Realm進行授權
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
????String principal = (String) principalCollection.getPrimaryPrincipal();
????List<Role> roles = userService.getRoleNameByUsername(principal);
????if(!CollectionUtils.isEmpty(roles)){
????????SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
????????roles.forEach(role-> simpleAuthorizationInfo.addRole(role.getName()));
????????roles.forEach(role->{
????????????List<String> perms = userService.getPermByRoleId(role.getId());
????????????simpleAuthorizationInfo.addStringPermissions(perms);
????????});
????????return simpleAuthorizationInfo;
????}
????return null;
}

九、Shiro與thymeleaf整合

9.1 導入依賴

<dependency>
????<groupId>com.github.theborakompanioni</groupId>
????<artifactId>thymeleaf-extras-shiro</artifactId>
????<version>2.0.0</version>
</dependency>

9.2 配置方言

@Bean
public ShiroDialect shiroDialect(){
????return new ShiroDialect();
}

9.3 引入工作空間

<html lang="en" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">

9.4 常用標簽使用

<!-- 驗證當前用戶是否為"訪客",即未認證的用戶 -->
<p shiro:guest="">未認證</p>

<!-- 認證通過或者已經"記住我"的用戶 -->
<p shiro:user="">hello</p>

<!-- 認證通過的用戶 -->
<p shiro:authenticated="">hello</p>

<!-- 輸出當前用戶信息,通常為賬號登錄信息 -->
<p shiro:principal></p>

<!-- 判斷當前用戶是否擁有該角色 -->
<p shiro:hasRole="admin">擁有該角色</p>

<!-- 當前用戶沒有該角色認證通過 -->
<p shiro:lacksRole="user">沒有改角色</p>

<!-- 判斷當前用戶是否擁有以下所有角色 -->
<p shiro:hasAllRoles="admin,user"></p>

<!-- 判斷當前用戶是否擁有以下任意一個角色 -->
<p shiro:hasAnyRoles="admin,user"></p>

<!-- 判斷當前用戶是否擁有以下權限字符串 -->
<p shiro:hasPermission="user:add"></p>

<!-- 當前用戶沒有該權限字符串認證通過 -->
<p shiro:lacksPermission="user:add"></p>

到了這里,關于Shiro安全框架簡介的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • 安全框架Spring Security是什么?如何理解Spring Security的權限管理?

    安全框架Spring Security是什么?如何理解Spring Security的權限管理?

    大家好,我是卷心菜。本篇主要講解Spring Security的基本介紹和架構分析,如果您看完文章有所收獲,可以三連支持博主哦~,嘻嘻。 ?? 作者簡介: 在校大學生一枚,Java領域新星創(chuàng)作者,Java、Python正在學習中,期待和大家一起學習一起進步~ ?? 個人主頁:我是一棵卷心菜的

    2024年02月02日
    瀏覽(24)
  • Shiro框架:Shiro SecurityManager安全管理器解析

    Shiro框架:Shiro SecurityManager安全管理器解析

    目錄 1.?SecurityManager介紹 1.1?Authenticator 1.2?Authorizer 1.3?SessionManager 2. DefaultWebSecurityManager解析 2.1?Destroyable 2.2?CacheManagerAware 2.3?EventBusAware 2.4?CachingSecurityManager(聚合緩存管理和事件監(jiān)聽管理功能) 2.5?RealmSecurityManager(聚合Realm管理功能) 2.6?AuthenticatingSecurityManager(聚合登

    2024年01月17日
    瀏覽(16)
  • 請簡單介紹一下Shiro框架是什么?Shiro在Java安全領域的主要作用是什么?Shiro主要提供了哪些安全功能

    請簡單介紹一下Shiro框架是什么?Shiro在Java安全領域的主要作用是什么?Shiro主要提供了哪些安全功能

    會話管理(Session Management):Shiro能夠管理用戶的會話狀態(tài),包括會話的創(chuàng)建、維護和銷毀。它支持多種會話存儲方式(如內存、數據庫等),并提供了會話超時、會話失效等機制,以確保會話的安全性。 跨平臺集成:Shiro不僅適用于Web應用程序,還可以輕松集成到桌面應用

    2024年04月13日
    瀏覽(29)
  • 請簡單介紹一下Shiro框架是什么?Shiro在Java安全領域的主要作用是什么?Shiro主要提供了哪些安全功能?

    請簡單介紹一下Shiro框架是什么? Shiro框架是一個強大且靈活的開源安全框架,為Java應用程序提供了全面的安全解決方案。它主要用于身份驗證、授權、加密和會話管理等功能,可以輕松地集成到任何Java Web應用程序中,并提供了易于理解和使用的API,使開發(fā)人員能夠快速實

    2024年04月11日
    瀏覽(25)
  • 【Java】一文帶你快速入門Shiro權限框架

    【Java】一文帶你快速入門Shiro權限框架

    ??推薦網站(不斷完善中):個人博客 ??個人主頁:個人主頁 ??相關專欄:CSDN專欄 ??立志賺錢,干活想躺,瞎分享的摸魚工程師一枚 在我們實戰(zhàn)開發(fā)過程中,對于權限的控制是必不可少的,一個系統(tǒng)中常見的有 普通會員、管理員、超級管理員 等等不同的角色出現。 我們

    2024年02月08日
    瀏覽(31)
  • shiro框架基本概念介紹

    shiro框架基本概念介紹

    Shiro 是一個強大靈活的開源安全框架,可以完全處理身份驗證、授權、加密和會話管理 身份驗證(Authentication):驗證用戶的身份,確保用戶是合法的。 授權(Authorization):控制用戶對系統(tǒng)資源的訪問權限,限制用戶只能訪問其被授權的部分。 會話管理(Session Management):

    2024年02月13日
    瀏覽(23)
  • 盤點國內前端npm CDN替代方案,基本上可以替代unpkg、jsdelivr

    收集一波常見的加速NPM包的CDN,發(fā)現有些還是挺好用的,基本上可以替代unpkg、jsdelivr,用來做博客或者網站加載NPM使用還是可以的。 unpkg.com cdn.jsdelivr.net fastly.jsdelivr.net 使用方法 :直接進官網,搜NPM包名使用。 缺點 :有時候不是很穩(wěn)定,而且國內有些地方沒法訪問,jsdel

    2023年04月17日
    瀏覽(56)
  • JAVA安全框架之shiro

    JAVA安全框架之shiro

    Apache Shiro 是一個功能強大且易于使用的 Java 安全(權限)框架 。Shiro 可以完 成: 認證、授權、加密、會話管理、與 Web 集成、緩存 等。借助 Shiro 您可以快速輕松 地保護任何應用程序——從最小的移動應用程序到最大的 Web 和企業(yè)應用程序。 官網 :https://shiro.apache.org/ ? ? s

    2024年02月15日
    瀏覽(59)
  • 利用Unity開發(fā)UI并接入HTC VIVE 手柄(基本上寫完了,挖個坑12.1開完會更新)

    利用Unity開發(fā)UI并接入HTC VIVE 手柄(基本上寫完了,挖個坑12.1開完會更新)

    Unity 2018.3(之前用2021.3,教程比較少,自己復寫很困難,就換了個版本)、HTC Vive Pro 2 專業(yè)套裝、SteamVR 安裝Unity資源包:SteamVR Plugin(SDK要求 1.14.15)、vive input unity、icons(可能還有補充) 比較重要的官方文檔: 目前發(fā)現了兩種做法 第①種將全景視頻渲染到整個skybox,讓天

    2024年02月05日
    瀏覽(220)
  • SSM 整合 Shiro 安全框架【快速入門】

    SSM 整合 Shiro 安全框架【快速入門】

    更改web路徑 創(chuàng)建所需目錄 屬性名與數據庫字段名一 一對應 這里只是為了測試項目,還沒有進行編碼工作 啟動tamcat服務 LoginVo

    2024年02月12日
    瀏覽(22)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包