如何用Springboot快速整合shiro安全框架
咱們先來普及一下什么是shiro,shiro原名Apache Shiro 是一個(gè)Java 的安全(權(quán)限)框架。Shiro 可以非常容易的開發(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)圖:


話不多說,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ù)庫 /*
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類
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)不能訪問此頁面";
}
//登錄操作
@RequestMapping("/login")
public String login(String username, String password, @RequestParam(defaultValue = "false")boolean rememberMe,Model model){
//使用shiro,編寫認(rèn)證操作
//1. 獲取Subject
Subject subject = SecurityUtils.getSubject();
//2. 封裝用戶的數(shù)據(jù)
UsernamePasswordToken token = new UsernamePasswordToken(username, password,rememberMe);
//3. 執(zhí)行登錄的方法,只要沒有異常就代表登錄成功!
try {
subject.login(token); //登錄成功!返回首頁
System.out.println("輸出認(rèn)證成功跳轉(zhuǎn)頁面");
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è)類
第一個(gè)類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;
//聲明為配置類
@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)置過濾器,常用的有如下過濾器:
anon: 無需認(rèn)證就可以訪問
authc: 必須認(rèn)證才可以訪問
user: 如果使用了記住我功能就可以直接訪問
perms: 擁有某個(gè)資源權(quán)限才可以訪問
role: 擁有某個(gè)角色權(quá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)頁面
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ù)庫的用戶名和密碼
// String name = "root";
// String password = "123456";
//1.判斷用戶名
UsernamePasswordToken userToken = (UsernamePasswordToken)token;
//連接真實(shí)的數(shù)據(jù)庫
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)類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層
先是類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,由于文件過多不變多寫,如果小伙伴們想要源碼可以直接私聊我博客賬號(hào)。
最后成功的成品如圖:
普通用戶登錄:


root用戶登錄


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

存入數(shù)據(jù)庫的數(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)文章
Java Web開發(fā)防止多用戶重復(fù)登錄的完美解決方案
在web項(xiàng)目開發(fā)中,很多情況下都可以讓同一個(gè)賬號(hào)信息在不同的登錄入口登錄很多次,這樣子做的不是很完善。一般解決這種情況有兩種解決方案,小編呢主要以第二種方式給大家介紹具體的實(shí)現(xiàn)方法,對(duì)java web 防止多用戶重復(fù)登錄的解決方案感興趣的朋友一起看看吧2016-11-11
基于Freemarker和xml實(shí)現(xiàn)Java導(dǎo)出word
這篇文章主要介紹了基于Freemarker和xml實(shí)現(xiàn)Java導(dǎo)出word,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-04-04
RocketMQ producer同步發(fā)送單向發(fā)送源碼解析
這篇文章主要為大家介紹了RocketMQ producer同步發(fā)送單向發(fā)送源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03
淺談resultMap的用法及關(guān)聯(lián)結(jié)果集映射
這篇文章主要介紹了resultMap的用法及關(guān)聯(lián)結(jié)果集映射操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06

