SpringBoot 整合 Shiro Thymeleaf Mysql 动态授权
生活随笔
收集整理的這篇文章主要介紹了
SpringBoot 整合 Shiro Thymeleaf Mysql 动态授权
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
文章目錄
- 需求安排
- 一、前期準備
- 1. maven依賴
- 2. 創建數據庫+初始化表數據
- 3. 實體類
- 4. mapper接口
- 5. mapper接口映射文件
- 6. service接口
- 7. service實現類
- 8. 首頁控制器
- 9. 用戶控制器
- 10. 全局配置文件
- 11. 啟動類加注解
- 二、頁面準備
- 2.1. 首頁頁面
- 2.2. 登錄頁面
- 2.3. 未授權頁面
- 2.4. 用戶添加頁面
- 2.5. 用戶更新頁面
- 三、Shiro 配置
- 3.1. 自定義UserRealm
- 3.2. ShiroConfig
- 四、需求測試
- 五、源碼鏈接
需求安排
需求分析: 1. 匿名允許訪問頁面首頁和登錄頁面 2. 默認登錄頁面 3. admin用戶只有用戶添加權限 4. test用戶只有用戶更新權限 5. 訪問授權頁面,默認跳轉登錄頁面 6. 登錄認證通過,訪問無權限頁面,默認跳轉未授權頁面 7. 登錄認證通過,進行資源授權角色授權后,訪問各自有權限的頁面 注:第6條企業內部采用無權限的頁面采用shiro和頁面整合策略,直接不會顯示一、前期準備
1. maven依賴
<properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.8</java.version><druid.version>1.0.28</druid.version><mybatis-spring-boot.version>2.1.2</mybatis-spring-boot.version><shiro-spring.version>1.5.2</shiro-spring.version><thymeleaf-extras-shiro.version>2.0.0</thymeleaf-extras-shiro.version></properties><dependencies><!--lombok--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><!--thymeleaf模板引擎--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><!--springMvc啟動器--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- shiro與spring整合依賴 --><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring</artifactId><version>${shiro-spring.version}</version></dependency><!--mybatis啟動器--><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>${mybatis-spring-boot.version}</version></dependency><!--MYSQL--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><!-- 集成druid數據源 --><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>${druid.version}</version></dependency><!-- thymel對shiro的擴展坐標 --><dependency><groupId>com.github.theborakompanioni</groupId><artifactId>thymeleaf-extras-shiro</artifactId><version>${thymeleaf-extras-shiro.version}</version></dependency></dependencies>2. 創建數據庫+初始化表數據
數據庫名:shiro
表名:user
3. 實體類
package com.gblfy.entity;import lombok.Data; import java.io.Serializable;@Data public class User implements Serializable {private Integer id;private String name;private String password;private String perms; }4. mapper接口
package com.gblfy.mapper;import com.gblfy.entity.User;public interface UserMapper {/*** 通過id查詢用戶信息** @param id* @return*/User selectByPrimaryKey(Integer id);/*** 根據用戶名查詢用戶信息** @param name* @return*/User selectByName(String name);}5. mapper接口映射文件
在resources目錄下面創建mapping文件夾
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" ><mapper namespace="com.gblfy.mapper.UserMapper"><resultMap id="BaseResultMap" type="com.gblfy.entity.User"><id column="id" property="id" jdbcType="INTEGER"/><result column="name" property="name" jdbcType="VARCHAR"/><result column="password" property="password" jdbcType="VARCHAR"/><result column="perms" property="perms" jdbcType="VARCHAR"/></resultMap><sql id="Base_Column_List">id, name, password, perms</sql><select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer">select<include refid="Base_Column_List"/>from userwhere id = #{id,jdbcType=INTEGER}</select><select id="selectByName" resultMap="BaseResultMap" parameterType="java.lang.String">select<include refid="Base_Column_List"/>from userwhere name = #{name,jdbcType=VARCHAR}</select> </mapper>6. service接口
package com.gblfy.service;import com.gblfy.entity.User;public interface UserService {/*** 根據用戶名查詢用戶信息** @param name* @return*/User selectByName(String name);/*** 通過id查詢用戶信息** @param id* @return*/User selectByPrimaryKey(Integer id); }7. service實現類
package com.gblfy.service.impl;import com.gblfy.entity.User; import com.gblfy.mapper.UserMapper; import com.gblfy.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service;@Service public class UserServiceImpl implements UserService {@Autowiredprivate UserMapper userMapper;/*** 根據用戶名查詢用戶信息** @param name* @return*/@Overridepublic User selectByName(String name) {return userMapper.selectByName(name);}/*** 通過id查詢用戶信息** @param id* @return*/@Overridepublic User selectByPrimaryKey(Integer id) {return userMapper.selectByPrimaryKey(id);}}8. 首頁控制器
package com.gblfy.controller;import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping;@Controller public class IndexController {@RequestMapping("index")public String index() {return "index";} }9. 用戶控制器
package com.gblfy.controller;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;@Controller public class UserController {//跳轉登錄頁面@RequestMapping("/toLogin")public String toLogin() {return "login";}//用戶添加@RequestMapping("/add")public String add() {return "/user/add";}//用戶更新@RequestMapping("/update")public String update() {return "/user/update";}//未授權跳轉頁面@RequestMapping("noAuth")public String noAuth() {return "noAuth";}//登錄處理@RequestMapping("login")public String login(String username, String password, Model model) {/*** 編寫shiro認證操作* 1.獲取subject* 2.封裝用戶數據* 3.執行登錄方法*///1.獲取subjectSubject subject = SecurityUtils.getSubject();//2.封裝用戶數據 認證時會用到UsernamePasswordToken token = new UsernamePasswordToken(username, password);//3.執行登錄方法try {subject.login(token);//登陸成功} catch (UnknownAccountException e) {e.printStackTrace();//登陸失敗 場景1model.addAttribute("msg", "用戶名不存在!");return "login";} catch (IncorrectCredentialsException e) {e.printStackTrace();//登陸失敗 場景2model.addAttribute("msg", "密碼錯誤!");return "login";}//登陸成功model.addAttribute("msg", username + "登陸成功跳轉首頁");return "index";} }10. 全局配置文件
#server 端口 server:port: 80tomcat:min-spare-threads: 30max-threads: 1000#Mysql配置 spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/shiro?useSSL=true&serverTimezone=GMT&allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8username: rootpassword: roottype: com.alibaba.druid.pool.DruidDataSource# Mybatis Mapper映射文件+實體類配置 mybatis:type-aliases-package: com.gblfy.entitymapperLocations:- classpath*:/mapping/*.xml11. 啟動類加注解
package com.gblfy;import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication @MapperScan("com.gblfy.mapper") public class SpringbootShiroApplication {public static void main(String[] args) {SpringApplication.run(SpringbootShiroApplication.class, args);}}二、頁面準備
2.1. 首頁頁面
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"xmlns:shiro="http://www.pollix.at/thymeleaf/shiro"><head><meta charset="UTF-8"><title>系統首頁</title> </head> <body> <h3 th:text="${msg}" style="color: red"></h3> <div>進入用戶添加頁面:   <a href="/add">用戶添加</a> </div> <br/> <div>進入用戶更新頁面:   <a href="/update">用戶更新</a> </div> </body> </html>2.2. 登錄頁面
<!DOCTYPE html> <html lang="zh" xmlns:th="http://www.thymeleaf.org"><head><meta charset="UTF-8"><title>登錄頁面</title> </head> <body> <h3 th:text="${msg}" style="color: red">登錄</h3> <form method="post" action="/login">用戶名:<input type="text" name="username"/><br/>密 碼:<input type="password" name="password"/><br/><input type="submit" value="登錄"/> </form> </body> </html>2.3. 未授權頁面
<!DOCTYPE html> <html lang="zh" xmlns:th="http://www.thymeleaf.org"><head><meta charset="UTF-8"><title>未授權頁面</title> </head> <body> 未授權頁面,請聯系管理員進行授權操作! </body> </html>2.4. 用戶添加頁面
<!DOCTYPE html> <html lang="zh" xmlns:th="http://www.thymeleaf.org"><head><meta charset="UTF-8"><title>添加頁面</title> </head> <body> <h3>添加頁面</h3> </body> </html>2.5. 用戶更新頁面
<!DOCTYPE html> <html lang="zh" xmlns:th="http://www.thymeleaf.org"><head><meta charset="UTF-8"><title>更新頁面</title> </head> <body> <h3>更新頁面</h3> </body> </html>三、Shiro 配置
3.1. 自定義UserRealm
package com.gblfy.realm;import com.gblfy.entity.User; import com.gblfy.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.springframework.beans.factory.annotation.Autowired;/*** 自定義 UserRealm* 固定寫法:extends AuthorizingRealm*/ public class UserRealm extends AuthorizingRealm {@Autowiredprivate UserService userService;/*** 認證** @param token* @return* @throws AuthenticationException*/@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {//1.得到用戶名和密碼 因為登錄已存,因此,能取UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;String username = usernamePasswordToken.getUsername();//默認獲取password的類型為char[],轉換處理String password = new String(usernamePasswordToken.getPassword());//2.從數據庫根據用戶名查詢用戶信息User user = userService.selectByName(username);//判斷查詢出的用戶對象(sysUser)是否為空if (user == null) {throw new UnknownAccountException("用戶不存在!");}//判斷查詢出的用戶對象的用戶密碼和頁面從頁面傳遞過來的密碼進行比較是否相同if (!user.getPassword().equals(password)) {throw new IncorrectCredentialsException("密碼有誤!");}//認證通過 登陸成功SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, user.getPassword(), this.getName());return info;}/*** 授權** @param principalCollection* @return*/@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();//通過id用戶信息Subject subject = SecurityUtils.getSubject();//認證時存的是user,因此可以強轉成user對象User user = (User) subject.getPrincipal();User userPerms = userService.selectByPrimaryKey(user.getId());//從user對象動態獲取權限,放到認證容器info.addStringPermission(userPerms.getPerms());return info;}}3.2. ShiroConfig
package com.gblfy.config;import com.gblfy.realm.UserRealm; 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 {/*** 1.創建Realm*/@Bean(name = "userRealm")public UserRealm getRealm() {return new UserRealm();}/*** 2.創建DefaultWebSecurityManager*/@Bean(name = "securityManager")public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm) {DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();//關聯realmsecurityManager.setRealm(userRealm);return securityManager;}/*** 3.創建ShiroFilterFactoryBean*/@Beanpublic ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager) {ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();//設置安全管理器shiroFilterFactoryBean.setSecurityManager(securityManager);//指定登錄頁面shiroFilterFactoryBean.setLoginUrl("/toLogin");//指定未授權頁面shiroFilterFactoryBean.setUnauthorizedUrl("/noAuth");//添加Shiro內置過濾器/*** Shiro內置過濾器,可以實現權限相關的攔截器* 常用的過濾器:* anon: 無需認證(登錄)可以訪問* authc: 必須認證才可以訪問* user: 如果使用rememberMe的功能可以直接訪問* perms: 該資源必須得到資源權限才可以訪問* role: 該資源必須得到角色權限才可以訪問*/Map<String, String> filterMap = new LinkedHashMap<String, String>();//設置允許匿名訪問filterMap.put("/index", "anon");filterMap.put("/login", "anon");//配置授權過濾器 第一種filterMap.put("/add", "perms[user:add]");filterMap.put("/update", "perms[user:update]");//授權才可以訪問filterMap.put("/*", "authc");shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);return shiroFilterFactoryBean;}}四、需求測試
測試計劃; 1. 訪問http://localhost/index和http://localhost/login 是否可以匿名訪問 2. 訪問http://localhost/index頁面,點擊進入添加頁面是否跳轉登錄頁面 3. 訪問http://localhost/index頁面,點擊進入更新頁面是否跳轉登錄頁面 4. 訪問幾個不存在的url測試是否默認統一跳轉登錄頁面。例如: http://localhost/xxx 5. 使用admin賬戶,訪問登錄頁面,做一下測試:1>輸入不存在的賬戶點擊登錄,不輸密碼,測試,是否提示用戶名不存在2>輸入存在的賬戶admin不輸密碼,點擊登錄,測試,是否提示密碼錯誤3>輸入存在的正確的賬戶admin,輸入正確的密碼,點擊登錄,測試,點擊用戶添加,是否可以進入用戶添加頁面4>輸入存在的正確的賬戶admin,輸入正確的密碼,點擊登錄,測試,點擊用戶更新,是否跳轉未授權頁面 6. 使用test賬戶,訪問登錄頁面,做一下測試:1>輸入不存在的賬戶點擊登錄,不輸密碼,測試,是否提示用戶名不存在2>輸入存在的賬戶test不輸密碼,點擊登錄,測試,是否提示密碼錯誤3>輸入存在的正確的賬戶test,輸入正確的密碼,點擊登錄,測試,點擊用戶更新,是否可以進入用戶更新頁面4>輸入存在的正確的賬戶test,輸入正確的密碼,點擊登錄,測試,點擊用戶添加,是否跳轉未授權頁面到此,除了成功登錄后,角色授權,就都演示完了!
五、源碼鏈接
總結
以上是生活随笔為你收集整理的SpringBoot 整合 Shiro Thymeleaf Mysql 动态授权的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PL/SQL提示“ORA-01722:无
- 下一篇: linux cmake编译源码,linu