如何用Springboot快速整合shiro安全框架
咱們先來(lái)普及一下什么是shiro,shiro原名Apache Shiro 是一個(gè)Java 的安全(權(quán)限)框架。Shiro 可以非常容易的開(kāi)發(fā)出足夠好的應(yīng)用,其不僅可以用在JavaSE環(huán)境,也可以用在JavaEE環(huán)境。Shiro可以完成,認(rèn)證,授權(quán),加密,會(huì)話管理,Web集成,緩存等高級(jí)應(yīng)用。下載地址:http://shiro.apac he.org/ 如圖看shiro的功能和架構(gòu)圖:


話不多說(shuō),Springboot整合shiro,咱們直接上代碼
pom.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.11</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo02</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo02</name>
<description>demo02</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.1</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.31</version>
</dependency>
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.12</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.18</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-java8time</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.0.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
然后我們建立一個(gè)數(shù)據(jù)庫(kù) /*
Navicat MySQL Data Transfer
Source Server :
Source Server Version : 80030
Source Host : localhost:3306
Source Database : mybatis
Target Server Type : MYSQL
Target Server Version : 80030
File Encoding : 65001
Date: 2023-03-14 18:00:05
*/
SET FOREIGN_KEY_CHECKS=0;
– Table structure for user
DROP TABLE IF EXISTS user;
CREATE TABLE user (id int NOT NULL AUTO_INCREMENT,name varchar(255) DEFAULT NULL,pwd varchar(255) DEFAULT NULL,perms varchar(100) DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
– Records of user
INSERT INTO user VALUES (‘1’, ‘qin’, ‘d1b129656359e35e95ebd56a63d7b9e0’, ‘user:add’);
INSERT INTO user VALUES (‘2’, ‘hai’, ‘123’, ‘user:insert’);
INSERT INTO user VALUES (‘3’, ‘root’, ‘d1b129656359e35e95ebd56a63d7b9e0’, ‘user:update’);
application.yml文件
spring:
datasource:
username: xxxx
password: xxxxxxxxxxxx
url: jdbc:mysql://localhost:3306/mybatis
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
mybatis:
mapper-locations: classpath:mapper/*tat.slowSqlMillis=500
controller層MyController類(lèi)
package com.example.demo02.controller;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@Slf4j
public class MyController {
@RequestMapping("/")
public String toIndex(Model model){
model.addAttribute("msg","hello,shiro");
return "login";
}
@RequestMapping("/user/add")
public String add(){
return "user/add";
}
@RequestMapping("/user/update")
public String update(){
return "user/update";
}
@RequestMapping("/toLogin")
public String toLogin(){
return "login";
}
@RequestMapping("/noauth")
@ResponseBody
public String noAuth(){
return "未經(jīng)授權(quán)不能訪問(wèn)此頁(yè)面";
}
//登錄操作
@RequestMapping("/login")
public String login(String username, String password, @RequestParam(defaultValue = "false")boolean rememberMe,Model model){
//使用shiro,編寫(xiě)認(rèn)證操作
//1. 獲取Subject
Subject subject = SecurityUtils.getSubject();
//2. 封裝用戶的數(shù)據(jù)
UsernamePasswordToken token = new UsernamePasswordToken(username, password,rememberMe);
//3. 執(zhí)行登錄的方法,只要沒(méi)有異常就代表登錄成功!
try {
subject.login(token); //登錄成功!返回首頁(yè)
System.out.println("輸出認(rèn)證成功跳轉(zhuǎn)頁(yè)面");
return "index";
} catch (UnknownAccountException e) { //用戶名不存在
model.addAttribute("msg","用戶名不存在");
return "login";
} catch (IncorrectCredentialsException e) { //密碼錯(cuò)誤
model.addAttribute("msg","密碼錯(cuò)誤");
return "login";
}
}
}
pojo層User
package com.example.demo02.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private int id;
private String name;
private String pwd;
private String perms;
}
config層配置兩個(gè)類(lèi)
第一個(gè)類(lèi)ShiroConfig
package com.example.demo02.config;
import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.LinkedHashMap;
import java.util.Map;
//聲明為配置類(lèi)
@Configuration
public class ShiroConfig {
//創(chuàng)建 ShiroFilterFactoryBean
@Bean
public ShiroFilterFactoryBean
getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager securityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
//設(shè)置安全管理器
shiroFilterFactoryBean.setSecurityManager(securityManager);
/*
添加Shiro內(nèi)置過(guò)濾器,常用的有如下過(guò)濾器:
anon: 無(wú)需認(rèn)證就可以訪問(wèn)
authc: 必須認(rèn)證才可以訪問(wèn)
user: 如果使用了記住我功能就可以直接訪問(wèn)
perms: 擁有某個(gè)資源權(quán)限才可以訪問(wèn)
role: 擁有某個(gè)角色權(quán)限才可以訪問(wèn)
*
/
*/
//進(jìn)行一個(gè)攔截
Map<String,String> filterMap = new LinkedHashMap<String, String>();
// filterMap.put("/user/add","authc");
// filterMap.put("/user/update","authc");
//授權(quán)
// filterMap.put("/user/add","perms[user:add]"); //大家記得注意順序!
filterMap.put("/user/add","perms[user:add]");
filterMap.put("/user/update","perms[user:update]");
filterMap.put("/user/*","authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
shiroFilterFactoryBean.setLoginUrl("/toLogin");
//未授權(quán)頁(yè)面
shiroFilterFactoryBean.setUnauthorizedUrl("/noauth");
return shiroFilterFactoryBean;
}
//創(chuàng)建 DefaultWebSecurityManager
@Bean(name = "securityManager")
public DefaultWebSecurityManager
getDefaultWebSecurityManager(@Qualifier("userRealm")UserRealm userRealm){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//2創(chuàng)建加密對(duì)象,設(shè)置相關(guān)屬性
HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
//2.1采用md5加密
matcher.setHashAlgorithmName("md5");
//2.2迭代加密次數(shù)
matcher.setHashIterations(3);
//3將加密對(duì)象存儲(chǔ)到myRealm中
userRealm.setCredentialsMatcher(matcher);
//關(guān)聯(lián)Realm
securityManager.setRealm(userRealm);
return securityManager;
}
//創(chuàng)建 realm 對(duì)象
@Bean
public UserRealm userRealm(){
return new UserRealm();
}
//配置ShiroDialect:方言,用于 thymeleaf 和 shiro 標(biāo)簽配合使用
@Bean
public ShiroDialect getShiroDialect(){
return new ShiroDialect();
}
}
UserRealm
package com.example.demo02.config;
import com.example.demo02.pojo.User;
import com.example.demo02.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
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.subject.Subject;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
//自定義得UserRaelm
public class UserRealm extends AuthorizingRealm {
@Autowired
UserService userService;
//授權(quán)
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("執(zhí)行了=》授權(quán)doGetAuthorizationInfo");
SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
// info.addStringPermission("user:update");
info.addStringPermission("user:add");
//拿到當(dāng)前用戶登陸對(duì)象
Subject subject= SecurityUtils.getSubject();
User currentUser= (User) subject.getPrincipal();//拿到User對(duì)象
info.addStringPermission(currentUser.getPerms());//設(shè)置當(dāng)前用戶對(duì)象
return info;
}
//執(zhí)行認(rèn)證邏輯
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("執(zhí)行了=>認(rèn)證邏輯AuthenticationToken");
//假設(shè)數(shù)據(jù)庫(kù)的用戶名和密碼
// String name = "root";
// String password = "123456";
//1.判斷用戶名
UsernamePasswordToken userToken = (UsernamePasswordToken)token;
//連接真實(shí)的數(shù)據(jù)庫(kù)
User user= userService.queryUserByName(userToken.getUsername());
//
if(user==null){
return null;
}
Subject subject = SecurityUtils.getSubject();
subject.getSession().setAttribute("loginUser",user);
//2. 驗(yàn)證密碼,我們可以使用一個(gè)AuthenticationInfo實(shí)現(xiàn)類(lèi)SimpleAuthenticationInfo
// shiro會(huì)自動(dòng)幫我們驗(yàn)證!重點(diǎn)是第二個(gè)參數(shù)就是要驗(yàn)證的密碼!
return new SimpleAuthenticationInfo(user, user.getPwd(),ByteSource.Util.bytes("salt"),"");
// if(user !=null){
// AuthenticationInfo info = new SimpleAuthenticationInfo(
// token.getPrincipal(),
// user.getPwd(),
// ByteSource.Util.bytes("salt"),
// token.getPrincipal().toString()
// );
// return info;
// }
// return null;
}
}
service層
先是類(lèi)UserServiceImpl
package com.example.demo02.service;
import com.example.demo02.mapper.UserMapper;
import com.example.demo02.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl implements UserService {
@Autowired
UserMapper userMapper;
@Override
public User queryUserByName(String name) {
return userMapper.queryUserByName(name);
}
}
再是接口UserService
package com.example.demo02.service;
import com.example.demo02.pojo.User;
public interface UserService {
public User queryUserByName(String name);
}
mapper層
接口Usermapper
package com.example.demo02.mapper;
import com.example.demo02.pojo.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;
@Repository
//@Mapper
public interface UserMapper {
@Select("select * from user where name=#{name}")
public User queryUserByName(@Param("name") String name);
}
再就是前端resources里面的static和templates,由于文件過(guò)多不變多寫(xiě),如果小伙伴們想要源碼可以直接私聊我博客賬號(hào)。
最后成功的成品如圖:
普通用戶登錄:


root用戶登錄


后端實(shí)現(xiàn)鑒權(quán)圖

存入數(shù)據(jù)庫(kù)的數(shù)據(jù)為加密文件

以上就是我對(duì)Springboot整合shiro的相關(guān)代碼了,小伙伴們,如果喜歡就去給博主點(diǎn)贊把。
到此這篇關(guān)于如何用Springboot快速整合shiro安全框架的文章就介紹到這了,更多相關(guān)Springboot整合shiro安全框架內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring AOP切點(diǎn)表達(dá)式使用及說(shuō)明
這篇文章主要介紹了Spring AOP切點(diǎn)表達(dá)式使用及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-05-05
java實(shí)現(xiàn)即時(shí)通信的完整步驟分享
這篇文章主要給大家介紹了關(guān)于java實(shí)現(xiàn)即時(shí)通信的完整步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09
Java黑盒測(cè)試之nextDate函數(shù)測(cè)試
這篇文章主要介紹了Java黑盒測(cè)試之nextDate函數(shù)測(cè)試,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)Java黑盒測(cè)試的小伙伴們有很大的幫助哦,需要的朋友可以參考下2021-05-05
解析Idea為什么不推薦使用@Autowired進(jìn)行Field注入
這篇文章主要介紹了Idea不推薦使用@Autowired進(jìn)行Field注入的原因,網(wǎng)上文章大部分都是介紹兩者的區(qū)別,沒(méi)有提到為什么,當(dāng)時(shí)想了好久想出了可能的原因,今天來(lái)總結(jié)一下2022-05-05
關(guān)于SpringSecurity配置403權(quán)限訪問(wèn)頁(yè)面的完整代碼
本文給大家分享SpringSecurity配置403權(quán)限訪問(wèn)頁(yè)面的完整代碼,配置之前和配置之后的詳細(xì)介紹,代碼簡(jiǎn)單易懂,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2021-06-06
PowerJob的ServerDiscoveryService工作流程源碼解讀
這篇文章主要為大家介紹了PowerJob的ServerDiscoveryService工作流程源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12
SpringMVC4 + MyBatis3 + SQL Server 2014整合教程(含增刪改查分頁(yè))
這篇文章主要給大家介紹了關(guān)于SpringMVC4 + MyBatis3 + SQL Server 2014整合的相關(guān)資料,文中包括介紹了增刪改查分頁(yè)等相關(guān)內(nèi)容,通過(guò)示例代碼介紹的非常詳細(xì),分享出來(lái)供大家參考學(xué)習(xí),下面來(lái)一起看看吧。2017-06-06

