如何用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類
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è)類
第一個(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)置過(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)類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,由于文件過(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)文章
Java Web開(kāi)發(fā)防止多用戶重復(fù)登錄的完美解決方案
在web項(xiàng)目開(kāi)發(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,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-04-04RocketMQ producer同步發(fā)送單向發(fā)送源碼解析
這篇文章主要為大家介紹了RocketMQ producer同步發(fā)送單向發(fā)送源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03java網(wǎng)上圖書(shū)商城(4)購(gòu)物車模塊1
這篇文章主要為大家詳細(xì)介紹了java網(wǎng)上圖書(shū)商城,購(gòu)物車模塊,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-12-12淺談resultMap的用法及關(guān)聯(lián)結(jié)果集映射
這篇文章主要介紹了resultMap的用法及關(guān)聯(lián)結(jié)果集映射操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06