【更新】看到很多博客寫 shiro權限認證的,都是一半的代碼,復制上根本不能使用,依賴文件對於小白來說,更是不知道使用什么依賴,所以我把相應的java文件的包 都一並帶上
spring-shiro屬於輕量級權限框架,即使spring-security更新換代,市場上大多數企業還是選擇shiro
廢話不多說 引入pom文件相關依賴
1 <!--日志管理--> 2 <dependency> 3 <groupId>org.slf4j</groupId> 4 <artifactId>slf4j-api</artifactId> 5 <version>1.7.16</version> 6 </dependency>
7 <!--shiro權限框架--> 8 <dependency> 9 <groupId>org.apache.shiro</groupId> 10 <artifactId>shiro-spring</artifactId> 11 <version>1.3.2</version> 12 </dependency>
導入之后 相關依賴包就會自動加載 shiro-core、shiro-spring、shiro-web等等 依賴版本還得根據shiro集成的spring版本進行加載(注意版本號)
設計登錄認證,就少不三張表。沒做過登錄認證的小白 仔細看,我在Shiro配置中,盡量的去加入注釋說明
先貼上我的 用戶,角色,權限 三張表的 java 對象
需求分析為:用戶角色 - 多對多
角色權限 - 多對多
注意:直接復制的同學,三張表的注解,各位可以忽略刪除 也可以學習使用 Spring-Data-Jpa 底層是 Hibernate,建表和查詢方便
三個關系告訴你了,其實只需要最后關聯的是 : 用戶 - 權限 這里不需要 role角色表(實際項目中可以選擇需要)

import lombok.Data; import lombok.ToString; @Data @ToString public class User { /** * * This field was generated by MyBatis Generator. * This field corresponds to the database column tb_users.user_id * * @mbg.generated */ private Integer userId; /** * * This field was generated by MyBatis Generator. * This field corresponds to the database column tb_users.user_name * * @mbg.generated */ private String userName; /** * * This field was generated by MyBatis Generator. * This field corresponds to the database column tb_users.password * * @mbg.generated */ private String password; /** * * This field was generated by MyBatis Generator. * This field corresponds to the database column tb_users.phone * * @mbg.generated */ private String phone; /** * * This field was generated by MyBatis Generator. * This field corresponds to the database column tb_users.email * * @mbg.generated */ private String email; /** * * This field was generated by MyBatis Generator. * This field corresponds to the database column tb_users.status * * @mbg.generated */ private Integer status; private String salt; public String getSalt() { return salt; } public void setSalt(String salt) { this.salt = salt; } /** * * This field was generated by MyBatis Generator. * This field corresponds to the database column tb_users.note * * @mbg.generated */ private String note; /** * * This field was generated by MyBatis Generator. * This field corresponds to the database column tb_users.create_time * * @mbg.generated */ private String createTime; /** * * This field was generated by MyBatis Generator. * This field corresponds to the database column tb_users.update_time * * @mbg.generated */ private String updateTime; /** * This method was generated by MyBatis Generator. * This method returns the value of the database column tb_users.user_id * * @return the value of tb_users.user_id * * @mbg.generated */ public Integer getUserId() { return userId; } /** * This method was generated by MyBatis Generator. * This method sets the value of the database column tb_users.user_id * * @param userId the value for tb_users.user_id * * @mbg.generated */ public void setUserId(Integer userId) { this.userId = userId; } /** * This method was generated by MyBatis Generator. * This method returns the value of the database column tb_users.user_name * * @return the value of tb_users.user_name * * @mbg.generated */ public String getUserName() { return userName; } /** * This method was generated by MyBatis Generator. * This method sets the value of the database column tb_users.user_name * * @param userName the value for tb_users.user_name * * @mbg.generated */ public void setUserName(String userName) { this.userName = userName == null ? null : userName.trim(); } /** * This method was generated by MyBatis Generator. * This method returns the value of the database column tb_users.password * * @return the value of tb_users.password * * @mbg.generated */ public String getPassword() { return password; } /** * This method was generated by MyBatis Generator. * This method sets the value of the database column tb_users.password * * @param password the value for tb_users.password * * @mbg.generated */ public void setPassword(String password) { this.password = password == null ? null : password.trim(); } /** * This method was generated by MyBatis Generator. * This method returns the value of the database column tb_users.phone * * @return the value of tb_users.phone * * @mbg.generated */ public String getPhone() { return phone; } /** * This method was generated by MyBatis Generator. * This method sets the value of the database column tb_users.phone * * @param phone the value for tb_users.phone * * @mbg.generated */ public void setPhone(String phone) { this.phone = phone == null ? null : phone.trim(); } /** * This method was generated by MyBatis Generator. * This method returns the value of the database column tb_users.email * * @return the value of tb_users.email * * @mbg.generated */ public String getEmail() { return email; } /** * This method was generated by MyBatis Generator. * This method sets the value of the database column tb_users.email * * @param email the value for tb_users.email * * @mbg.generated */ public void setEmail(String email) { this.email = email == null ? null : email.trim(); } /** * This method was generated by MyBatis Generator. * This method returns the value of the database column tb_users.status * * @return the value of tb_users.status * * @mbg.generated */ public Integer getStatus() { return status; } /** * This method was generated by MyBatis Generator. * This method sets the value of the database column tb_users.status * * @param status the value for tb_users.status * * @mbg.generated */ public void setStatus(Integer status) { this.status = status; } /** * This method was generated by MyBatis Generator. * This method returns the value of the database column tb_users.note * * @return the value of tb_users.note * * @mbg.generated */ public String getNote() { return note; } /** * This method was generated by MyBatis Generator. * This method sets the value of the database column tb_users.note * * @param note the value for tb_users.note * * @mbg.generated */ public void setNote(String note) { this.note = note == null ? null : note.trim(); } /** * This method was generated by MyBatis Generator. * This method returns the value of the database column tb_users.create_time * * @return the value of tb_users.create_time * * @mbg.generated */ public String getCreateTime() { return createTime; } /** * This method was generated by MyBatis Generator. * This method sets the value of the database column tb_users.create_time * * @param createTime the value for tb_users.create_time * * @mbg.generated */ public void setCreateTime(String createTime) { this.createTime = createTime; } /** * This method was generated by MyBatis Generator. * This method returns the value of the database column tb_users.update_time * * @return the value of tb_users.update_time * * @mbg.generated */ public String getUpdateTime() { return updateTime; } /** * This method was generated by MyBatis Generator. * This method sets the value of the database column tb_users.update_time * * @param updateTime the value for tb_users.update_time * * @mbg.generated */ public void setUpdateTime(String updateTime) { this.updateTime = updateTime; } }

import lombok.Data; import lombok.ToString; import java.util.Date; /** * @author wusiwee * @date 2020/4/3 10:58 */ @Data @ToString public class Permission { /** * * This field was generated by MyBatis Generator. * This field corresponds to the database column tb_functions.func_id * * @mbg.generated */ private Integer funcId; /** * * This field was generated by MyBatis Generator. * This field corresponds to the database column tb_functions.func_name * * @mbg.generated */ private String funcName; /** * * This field was generated by MyBatis Generator. * This field corresponds to the database column tb_functions.func_url * * @mbg.generated */ private String funcUrl; /** * * This field was generated by MyBatis Generator. * This field corresponds to the database column tb_functions.func_code * * @mbg.generated */ private String funcCode; /** * * This field was generated by MyBatis Generator. * This field corresponds to the database column tb_functions.parent_id * * @mbg.generated */ private Integer parentId; /** * * This field was generated by MyBatis Generator. * This field corresponds to the database column tb_functions.func_type * * @mbg.generated */ private Integer funcType; /** * * This field was generated by MyBatis Generator. * This field corresponds to the database column tb_functions.status * * @mbg.generated */ private Integer status; /** * * This field was generated by MyBatis Generator. * This field corresponds to the database column tb_functions.sort_num * * @mbg.generated */ private Integer sortNum; /** * * This field was generated by MyBatis Generator. * This field corresponds to the database column tb_functions.create_time * * @mbg.generated */ private Date createTime; /** * * This field was generated by MyBatis Generator. * This field corresponds to the database column tb_functions.update_time * * @mbg.generated */ private Date updateTime; /** * This method was generated by MyBatis Generator. * This method returns the value of the database column tb_functions.func_id * * @return the value of tb_functions.func_id * * @mbg.generated */ public Integer getFuncId() { return funcId; } /** * This method was generated by MyBatis Generator. * This method sets the value of the database column tb_functions.func_id * * @param funcId the value for tb_functions.func_id * * @mbg.generated */ public void setFuncId(Integer funcId) { this.funcId = funcId; } /** * This method was generated by MyBatis Generator. * This method returns the value of the database column tb_functions.func_name * * @return the value of tb_functions.func_name * * @mbg.generated */ public String getFuncName() { return funcName; } /** * This method was generated by MyBatis Generator. * This method sets the value of the database column tb_functions.func_name * * @param funcName the value for tb_functions.func_name * * @mbg.generated */ public void setFuncName(String funcName) { this.funcName = funcName == null ? null : funcName.trim(); } /** * This method was generated by MyBatis Generator. * This method returns the value of the database column tb_functions.func_url * * @return the value of tb_functions.func_url * * @mbg.generated */ public String getFuncUrl() { return funcUrl; } /** * This method was generated by MyBatis Generator. * This method sets the value of the database column tb_functions.func_url * * @param funcUrl the value for tb_functions.func_url * * @mbg.generated */ public void setFuncUrl(String funcUrl) { this.funcUrl = funcUrl == null ? null : funcUrl.trim(); } /** * This method was generated by MyBatis Generator. * This method returns the value of the database column tb_functions.func_code * * @return the value of tb_functions.func_code * * @mbg.generated */ public String getFuncCode() { return funcCode; } /** * This method was generated by MyBatis Generator. * This method sets the value of the database column tb_functions.func_code * * @param funcCode the value for tb_functions.func_code * * @mbg.generated */ public void setFuncCode(String funcCode) { this.funcCode = funcCode == null ? null : funcCode.trim(); } /** * This method was generated by MyBatis Generator. * This method returns the value of the database column tb_functions.parent_id * * @return the value of tb_functions.parent_id * * @mbg.generated */ public Integer getParentId() { return parentId; } /** * This method was generated by MyBatis Generator. * This method sets the value of the database column tb_functions.parent_id * * @param parentId the value for tb_functions.parent_id * * @mbg.generated */ public void setParentId(Integer parentId) { this.parentId = parentId; } /** * This method was generated by MyBatis Generator. * This method returns the value of the database column tb_functions.func_type * * @return the value of tb_functions.func_type * * @mbg.generated */ public Integer getFuncType() { return funcType; } /** * This method was generated by MyBatis Generator. * This method sets the value of the database column tb_functions.func_type * * @param funcType the value for tb_functions.func_type * * @mbg.generated */ public void setFuncType(Integer funcType) { this.funcType = funcType; } /** * This method was generated by MyBatis Generator. * This method returns the value of the database column tb_functions.status * * @return the value of tb_functions.status * * @mbg.generated */ public Integer getStatus() { return status; } /** * This method was generated by MyBatis Generator. * This method sets the value of the database column tb_functions.status * * @param status the value for tb_functions.status * * @mbg.generated */ public void setStatus(Integer status) { this.status = status; } /** * This method was generated by MyBatis Generator. * This method returns the value of the database column tb_functions.sort_num * * @return the value of tb_functions.sort_num * * @mbg.generated */ public Integer getSortNum() { return sortNum; } /** * This method was generated by MyBatis Generator. * This method sets the value of the database column tb_functions.sort_num * * @param sortNum the value for tb_functions.sort_num * * @mbg.generated */ public void setSortNum(Integer sortNum) { this.sortNum = sortNum; } /** * This method was generated by MyBatis Generator. * This method returns the value of the database column tb_functions.create_time * * @return the value of tb_functions.create_time * * @mbg.generated */ public Date getCreateTime() { return createTime; } /** * This method was generated by MyBatis Generator. * This method sets the value of the database column tb_functions.create_time * * @param createTime the value for tb_functions.create_time * * @mbg.generated */ public void setCreateTime(Date createTime) { this.createTime = createTime; } /** * This method was generated by MyBatis Generator. * This method returns the value of the database column tb_functions.update_time * * @return the value of tb_functions.update_time * * @mbg.generated */ public Date getUpdateTime() { return updateTime; } /** * This method was generated by MyBatis Generator. * This method sets the value of the database column tb_functions.update_time * * @param updateTime the value for tb_functions.update_time * * @mbg.generated */ public void setUpdateTime(Date updateTime) { this.updateTime = updateTime; } }
開始進入Shiro篇
一:自定義Reaml域,用於實現自身認證體系,大白話:什么樣的認證規則,我都可以來定
創建Reaml對象 繼承 AuthorizingRealm 實現
授權方法
doGetAuthorizationInfo(PrincipalCollection principals){}
認證方法
doGetAuthenticationInfo(AuthenticationToken token){}
import com.bear.entity.Permission; import com.bear.entity.User; import com.bear.service.PermissionService; import com.bear.service.UserService; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.SimpleAuthenticationInfo; 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.springframework.beans.factory.annotation.Autowired; import java.util.ArrayList; import java.util.List; /** * @author wusw * @version 1.0 * @date 2020/4/2 19:46 */ public class ShiroReaml extends AuthorizingRealm { /** * 注入userService 服務層 用戶與數據庫數據查詢 */ @Autowired private UserService userService; /** * 注入permissionService 服務層 用戶與數據庫數據查詢 */ @Autowired private PermissionService permissionService; /** * 授權 * @param principalCollection * @return */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { //這個User對應下面認證方法的 返回的第一個參數 ew SimpleAuthenticationInfo(user, user.getPassword(), "shiroReaml") User user = (User)principalCollection.getPrimaryPrincipal(); //查詢用戶相關權限 List<Permission> permissionList = permissionService.findPermissionByUserId(user.getUserId()); //授權對象 SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); //創建一個List<String> 用於接收權限信息 ArrayList<String> list = new ArrayList<>(); for (Permission permission : permissionList) { //添加權限String字符串:存值示例: "admin:*","admin:list"... info.addStringPermission(permission.getFuncCode()); } return info; } /** * 認證 * @param token * @return * @throws AuthenticationException */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { //這一塊toString返回 username 是login方法在 newUserNamePassword(username,password)創建的token封裝成的 String username = token.getPrincipal().toString(); //打印一下,項目中 盡量不要使用System.out.println(),最好使用log日志進行記錄 System.out.println("認證獲取的username:"+username); //查詢數據庫用戶是否存在 不存在則拋異常 Shiro會自動認證失敗 User user = this.userService.findByUsername(username); //參數一 可以傳 username,user對象 等等 我這里是user對象 對應上面授權方法principalCollection獲取的值 //參數二 用戶密碼 //參數三 shiroReaml 名稱要與 shiroConfig配置中的 Reaml 的注入Bean保持一致 SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user, user.getPassword(), "shiroReaml"); return authenticationInfo; } }
二:Shiro配置 加上注解 @Configuration 讓springboot識別它為一個配置類
注意:打字太多,我把相應規則的 url 貼上,供大家參考
import org.apache.shiro.mgt.SecurityManager; 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.HashMap; /** * 請注意看每個方法上的注釋 * @author wusw * @version 1.0 * @date 2020/4/2 19:41 */ @Configuration public class ShiroConfig { /** * 添加創建 securityMeneger 工廠注入Bean * @param securityManager 注解Qualifier中的名字 和下面 DefaultWebSecurityManager 的Bean的名字相同 * @return */ @Bean public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("securityManager") SecurityManager securityManager){ ShiroFilterFactoryBean filterFactoryBean = new ShiroFilterFactoryBean(); filterFactoryBean.setSecurityManager(securityManager); //設置權限過濾器集合 key-value 形式 // key :訪問路徑 正常/**寫在最下面,執行順序是從上至下,這里是個大坑,一不小心,程序就涼涼了呢~ // value:anon(可以匿名訪問),authc(認證后才能訪問),logout(退出后自動清除session) HashMap<String, String> map = new HashMap<>(); map.put("/bear/login","anon"); map.put("/bear/logout","logout"); map.put("/**","authc"); filterFactoryBean.setLoginUrl("/bear/toLogin"); filterFactoryBean.setUnauthorizedUrl("/bear/401"); filterFactoryBean.setSuccessUrl("/bear/index"); //將map集合 傳給過濾器 filterFactoryBean.setFilterChainDefinitionMap(map); return filterFactoryBean; } /** * 創建 securityMeneger 類的注入Bean * @param shiroReaml 注解Qualifier中的名字 和下面 ShiroReaml的Bean的名字相同 * @return */ @Bean("securityManager") public DefaultWebSecurityManager defaultWebSecurityManager(@Qualifier("shiroReaml") ShiroReaml shiroReaml){ DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(shiroReaml); return securityManager; } /** * 創建自定義域 reaml注入Bean * @return */ @Bean("shiroReaml") public ShiroReaml shiroReaml(){ return new ShiroReaml(); } }
主要已經搞定,貼上相關service,controller,以及yml配置文件,dao層交互我使用的是mybaties相關pom依賴各位小伙伴自己導入 xml中namespase和type路徑請自行導入

# 數據庫的配置信息 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://0.0.0.0/db?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=Hongkong&verifyServerCertificate=false username: *** password: *** type: com.alibaba.druid.pool.DruidDataSource thymeleaf: mode: HTML5 encoding: UTF-8 servlet: content-type: text/html mvc: static-path-pattern: /** # mybatis的配置信息 mybatis: config-location: classpath:mybatis/config/mybatis-config.xml mapper-locations: classpath:mybatis/mapper/*.xml server: port: 8081

<?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.bear.dao.IUserMapper"> <resultMap id="BaseResultMap" type="com.bear.entity.User"> <!-- WARNING - @mbg.generated This element is automatically generated by MyBatis Generator, do not modify. --> <id column="user_id" jdbcType="INTEGER" property="userId" /> <result column="user_name" jdbcType="VARCHAR" property="userName" /> <result column="password" jdbcType="VARCHAR" property="password" /> <result column="phone" jdbcType="VARCHAR" property="phone" /> <result column="email" jdbcType="VARCHAR" property="email" /> <result column="salt" jdbcType="VARCHAR" property="salt" /> <result column="status" jdbcType="INTEGER" property="status" /> <result column="note" jdbcType="VARCHAR" property="note" /> <result column="create_time" jdbcType="TIMESTAMP" property="createTime" /> <result column="update_time" jdbcType="TIMESTAMP" property="updateTime" /> </resultMap> <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer"> <!-- WARNING - @mbg.generated This element is automatically generated by MyBatis Generator, do not modify. --> delete from tb_users where user_id = #{userId,jdbcType=INTEGER} </delete> <insert id="insert" parameterType="com.bear.entity.User"> insert into tb_users (user_id, user_name, password, phone, email, status, note, create_time, update_time ) values (#{userId,jdbcType=INTEGER}, #{userName,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR}, #{phone,jdbcType=VARCHAR}, #{email,jdbcType=VARCHAR}, #{status,jdbcType=INTEGER}, #{note,jdbcType=VARCHAR}, #{createTime,jdbcType=TIMESTAMP}, #{updateTime,jdbcType=TIMESTAMP} ) </insert> <update id="updateByPrimaryKey" parameterType="com.bear.entity.User"> <!-- WARNING - @mbg.generated This element is automatically generated by MyBatis Generator, do not modify. --> update tb_users set user_name = #{userName,jdbcType=VARCHAR}, password = #{password,jdbcType=VARCHAR}, phone = #{phone,jdbcType=VARCHAR}, email = #{email,jdbcType=VARCHAR}, status = #{status,jdbcType=INTEGER}, note = #{note,jdbcType=VARCHAR}, create_time = #{createTime,jdbcType=TIMESTAMP}, update_time = #{updateTime,jdbcType=TIMESTAMP} where user_id = #{userId,jdbcType=INTEGER} </update> <!-- <select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap"> select user_id, user_name, password, phone, email, status, note, create_time, update_time from tb_users where user_id = #{userId,jdbcType=INTEGER} </select>--> <select id="findAll" resultMap="BaseResultMap"> select user_id, user_name, password, phone, email, status, note, create_time, update_time from tb_users </select> <!-- 根據用戶名密碼查詢 --> <select id="findByUsername" resultMap="BaseResultMap"> select * from tb_users where user_name = #{username} </select> <!-- 根據分頁查詢 --> <!-- <select id="findByPage" resultMap="BaseResultMap"> select * from tb_users limit #{page},#{rows} </select> <!– 統計總記錄數 –> <select id="totalCount" resultType="long"> select count(*) from tb_users </select> <!– 根據ID查詢 –> <select id="findById" resultMap="BaseResultMap"> select * from tb_users where user_id = #{userId} </select>--> </mapper>

<?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.bear.dao.IPermissionMapper"> <resultMap id="BaseResultMap" type="com.bear.entity.Permission"> <!-- WARNING - @mbg.generated This element is automatically generated by MyBatis Generator, do not modify. --> <id column="func_id" jdbcType="INTEGER" property="funcId" /> <result column="func_name" jdbcType="VARCHAR" property="funcName" /> <result column="func_url" jdbcType="VARCHAR" property="funcUrl" /> <result column="func_code" jdbcType="VARCHAR" property="funcCode" /> <result column="parent_id" jdbcType="INTEGER" property="parentId" /> <result column="func_type" jdbcType="INTEGER" property="funcType" /> <result column="status" jdbcType="INTEGER" property="status" /> <result column="sort_num" jdbcType="INTEGER" property="sortNum" /> <result column="create_time" jdbcType="TIMESTAMP" property="createTime" /> <result column="update_time" jdbcType="TIMESTAMP" property="updateTime" /> </resultMap> <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer"> <!-- WARNING - @mbg.generated This element is automatically generated by MyBatis Generator, do not modify. --> delete from tb_functions where func_id = #{funcId,jdbcType=INTEGER} </delete> <insert id="insert" parameterType="com.bear.entity.Permission"> <!-- WARNING - @mbg.generated This element is automatically generated by MyBatis Generator, do not modify. --> insert into tb_functions (func_id, func_name, func_url, func_code, parent_id, func_type, status, sort_num, create_time, update_time) values (#{funcId,jdbcType=INTEGER}, #{funcName,jdbcType=VARCHAR}, #{funcUrl,jdbcType=VARCHAR}, #{funcCode,jdbcType=VARCHAR}, #{parentId,jdbcType=INTEGER}, #{funcType,jdbcType=INTEGER}, #{status,jdbcType=INTEGER}, #{sortNum,jdbcType=INTEGER}, #{createTime,jdbcType=TIMESTAMP}, #{updateTime,jdbcType=TIMESTAMP}) </insert> <update id="updateByPrimaryKey" parameterType="com.bear.entity.Permission"> <!-- WARNING - @mbg.generated This element is automatically generated by MyBatis Generator, do not modify. --> update tb_functions set func_name = #{funcName,jdbcType=VARCHAR}, func_url = #{funcUrl,jdbcType=VARCHAR}, func_code = #{funcCode,jdbcType=VARCHAR}, parent_id = #{parentId,jdbcType=INTEGER}, func_type = #{funcType,jdbcType=INTEGER}, status = #{status,jdbcType=INTEGER}, sort_num = #{sortNum,jdbcType=INTEGER}, create_time = #{createTime,jdbcType=TIMESTAMP}, update_time = #{updateTime,jdbcType=TIMESTAMP} where func_id = #{funcId,jdbcType=INTEGER} </update> <select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap"> <!-- WARNING - @mbg.generated This element is automatically generated by MyBatis Generator, do not modify. --> select func_id, func_name, func_url, func_code, parent_id, func_type, status, sort_num, create_time, update_time from tb_functions where func_id = #{funcId,jdbcType=INTEGER} </select> <select id="selectAll" resultMap="BaseResultMap"> <!-- WARNING - @mbg.generated This element is automatically generated by MyBatis Generator, do not modify. --> select func_id, func_name, func_url, func_code, parent_id, func_type, status, sort_num, create_time, update_time from tb_functions </select> <select id="findByRoleIds" resultMap="BaseResultMap" parameterType="java.util.List"> select distinct f.* from tb_functions f , tb_role_function rf where f.func_id = rf.func_id and rf.role_id in <foreach collection="list" item="id" open="(" close=")" separator=","> #{id} </foreach> and f.func_type = 0 </select> <select id="findPermissionByUserId" resultMap="BaseResultMap" parameterType="int"> select DISTINCT f.* from tb_users u,tb_user_role ur,tb_roles r,tb_functions f,tb_role_function rf where u.user_id = ur.user_id and r.role_id = ur.role_id and f.func_id = rf.func_id and r.role_id = rf.role_id and u.user_id = #{userId} </select> </mapper>
dao層:

import org.apache.ibatis.annotations.Mapper; import java.util.List; @Mapper public interface IUserMapper { /** * 根據用戶名查找用戶 * @param username * @return */ User findByUsername(String username); /** * 更新 * @param user */ void updateByPrimaryKey(User user); /** * 新增 * @param user */ void insert(User user); /** * 根據id刪除用戶(后期修改為改變狀態) * @param id */ void deleteByPrimaryKey(Integer id); /** * 查詢所有用戶列表 * @return */ List<User> findAll(); }

import org.apache.ibatis.annotations.Mapper; import java.util.List; /** * @author wusiwee * @date 2020/4/3 11:00 */ @Mapper public interface IPermissionMapper { /** * 根據user id查詢用戶權限 * @param userId * @return */ List<Permission> findPermissionByUserId(Integer userId); }
service層:

import java.util.List; public interface UserService { User findByUsername(String username); List<User> findAll(); }

import com.bear.dao.IUserMapper; import com.bear.entity.User; import com.bear.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; @Service public class UserServiceImpl implements UserService { @Autowired private IUserMapper userMapper; @Override public User findByUsername(String username) { User result = null; if (username != null) { result = this.userMapper.findByUsername(username); } return result; } @Override public List<User> findAll() { return this.userMapper.findAll(); } }

import com.bear.entity.Permission; import java.util.List; /** * @author wusiwee * @date 2020/4/3 11:02 */ public interface PermissionService { List<Permission> findPermissionByUserId(Integer userId); }

import com.bear.dao.IPermissionMapper; import com.bear.entity.Permission; import com.bear.service.PermissionService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; /** * @author wusiwee * @date 2020/4/3 11:02 */ @Service public class PermissionServiceImpl implements PermissionService { @Autowired private IPermissionMapper permissionMapper; @Override public List<Permission> findPermissionByUserId(Integer userId) { List<Permission> result = null; if (userId != null) { result = this.permissionMapper.findPermissionByUserId(userId); } return result; } }
controller層(注意Login方法的subject為shiro登錄使用):
注解@RequiresPermissions("system:*")為校驗用戶是否有權限,沒有此權限則不允許訪問此方法 跳轉401

import com.bear.service.UserService; import org.apache.commons.lang3.StringUtils; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.authz.annotation.RequiresPermissions; import org.apache.shiro.subject.Subject; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; @Controller @RequestMapping("/bear") public class LoginController { @Autowired private UserService userService; @GetMapping("toLogin") public String toLogin(){ return "login"; } @GetMapping("/login") public String login(String username, String password, Model model){ if (!StringUtils.isEmpty(username) && !StringUtils.isEmpty(password)){ //進行登錄驗證 Subject subject = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken(username, password); try { subject.login(token); //認證 boolean authenticated = subject.isAuthenticated(); if (authenticated){ //獲取當前對象,存入session User user = (User)subject.getPrincipal(); subject.getSession().setAttribute("user",user); System.out.println("登陸成功"); return "redirect:index"; }else { model.addAttribute("msg","登錄認證失敗!"); return "login"; } }catch (Exception e){ model.addAttribute("msg","登錄認證失敗!"); return "login"; } } return "login"; } @RequestMapping("/index") public String index(Model model){ model.addAttribute("userList",this.userService.findAll()); return "index"; } @RequestMapping("/logout") public String index(){ return "redirect:login"; } @RequestMapping("/401") public String fours(){ return "401"; } @RequiresPermissions("system") @RequestMapping("/success") public String success(){ return "success"; } }
html 頁面:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>成功頁面</title>
</head>
<body>
SUCCESS!
</body>
</html>

<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>登錄頁面</title> </head> <body> <h2>歡迎來到登錄頁面!</h2> <form action="/bear/login" method="GET" name="loginForm"> 登錄用戶:<input type="text" name="username" value=""><br/> 登錄密碼:<input type="text" name="password" value=""><br/> <input type="submit" name="log" value="登錄"> </form> <!--/*@thymesVar id="msg" type="at"*/--> <div th:text="${msg}"></div> </body> </html>

<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>首面</title> </head> <style> table{ border: 1px solid grey; border-collapse: collapse; } table td{ border: 1px solid grey; border-collapse: collapse; } </style> <body> <h2>用戶列表頁面</h2> <table> <tr> <td>用戶ID</td> <td>用戶名</td> <td>手機號</td> <td>郵箱</td> <td>狀態</td> <td>創建時間</td> </tr> <tr th:each="user:${userList}"> <td th:text="${user.userId}"></td> <td th:text="${user.userName}"></td> <td th:text="${user.phone}"></td> <td th:text="${user.email}"></td> <td th:text="${user.status == 1?'正常':'失效'}">正常</td> <td th:text="${user.createTime}"></td> </tr> </table> <form action="/bear/logout" method="get"> <input type="submit" value="退出"> </form> </body> </html>

<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>401沒有認證</title> </head> <body> <h2>抱歉,您的權限不足或認證失敗,請重新登錄!</h2> </body> </html>
配置完成
啟動運行Applicaiton.java,最后一行,啟動成功

. ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.2.6.RELEASE) 2020-04-07 15:11:42.580 INFO 14672 --- [ main] com.bear.PublicApplication : Starting PublicApplication on shands-siwee with PID 14672 (D:\java\GitProjects\bear-world\target\classes started by Shands-New in D:\java\GitProjects\bear-world) 2020-04-07 15:11:42.584 INFO 14672 --- [ main] com.bear.PublicApplication : No active profile set, falling back to default profiles: default 2020-04-07 15:11:43.534 INFO 14672 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'shiroConfig' of type [com.bear.shiro.ShiroConfig$$EnhancerBySpringCGLIB$$45102fe0] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2020-04-07 15:11:43.599 INFO 14672 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'mybatis-org.mybatis.spring.boot.autoconfigure.MybatisProperties' of type [org.mybatis.spring.boot.autoconfigure.MybatisProperties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2020-04-07 15:11:43.604 INFO 14672 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration' of type [org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration$$EnhancerBySpringCGLIB$$6a2f2642] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2020-04-07 15:11:43.605 INFO 14672 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration$Generic' of type [org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration$Generic] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2020-04-07 15:11:43.617 INFO 14672 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'spring.datasource-org.springframework.boot.autoconfigure.jdbc.DataSourceProperties' of type [org.springframework.boot.autoconfigure.jdbc.DataSourceProperties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2020-04-07 15:11:43.665 INFO 14672 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'dataSource' of type [com.alibaba.druid.pool.DruidDataSource] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2020-04-07 15:11:43.677 INFO 14672 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.boot.autoconfigure.jdbc.DataSourceInitializerInvoker' of type [org.springframework.boot.autoconfigure.jdbc.DataSourceInitializerInvoker] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2020-04-07 15:11:43.923 INFO 14672 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'sqlSessionFactory' of type [org.apache.ibatis.session.defaults.DefaultSqlSessionFactory] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2020-04-07 15:11:43.926 INFO 14672 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'sqlSessionTemplate' of type [org.mybatis.spring.SqlSessionTemplate] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2020-04-07 15:11:43.928 INFO 14672 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'IUserMapper' of type [org.mybatis.spring.mapper.MapperFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2020-04-07 15:11:43.929 INFO 14672 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'IUserMapper' of type [com.sun.proxy.$Proxy63] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2020-04-07 15:11:43.929 INFO 14672 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'userServiceImpl' of type [com.bear.service.impl.UserServiceImpl] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2020-04-07 15:11:43.932 INFO 14672 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'IPermissionMapper' of type [org.mybatis.spring.mapper.MapperFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2020-04-07 15:11:43.932 INFO 14672 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'IPermissionMapper' of type [com.sun.proxy.$Proxy64] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2020-04-07 15:11:43.932 INFO 14672 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'permissionServiceImpl' of type [com.bear.service.impl.PermissionServiceImpl] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2020-04-07 15:11:43.933 INFO 14672 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'shiroReaml' of type [com.bear.shiro.ShiroReaml] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2020-04-07 15:11:44.601 INFO 14672 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'securityManager' of type [org.apache.shiro.web.mgt.DefaultWebSecurityManager] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2020-04-07 15:11:44.857 INFO 14672 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8081 (http) 2020-04-07 15:11:44.868 INFO 14672 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat] 2020-04-07 15:11:44.868 INFO 14672 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.33] 2020-04-07 15:11:45.041 INFO 14672 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext 2020-04-07 15:11:45.042 INFO 14672 --- [ main] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 2400 ms 2020-04-07 15:11:45.231 INFO 14672 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor' 2020-04-07 15:11:45.301 INFO 14672 --- [ main] o.s.b.a.w.s.WelcomePageHandlerMapping : Adding welcome page template: index 2020-04-07 15:11:45.356 WARN 14672 --- [ main] org.thymeleaf.templatemode.TemplateMode : [THYMELEAF][main] Template Mode 'HTML5' is deprecated. Using Template Mode 'HTML' instead. 2020-04-07 15:11:45.455 INFO 14672 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8081 (http) with context path '' 2020-04-07 15:11:45.458 INFO 14672 --- [ main] com.bear.PublicApplication : Started PublicApplication in 3.516 seconds (JVM running for 4.842)
測試訪問 :localhost:8081/bear/index ——>此時是被攔截的,會自動跳轉toLogin到登錄頁面