SpringBoot整合Shiro权限框架

Shiro是一个非常不错的权限框架,它提供了登录和权限验证功能,如果想去了解它的话可以去Shiro官网学习  点击打开

1.创建数据库脚本

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for module
-- ----------------------------
DROP TABLE IF EXISTS `module`;
CREATE TABLE `module`  (
  `mid` int(11) NOT NULL AUTO_INCREMENT,
  `mname` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`mid`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

-- ----------------------------
-- Records of module
-- ----------------------------
INSERT INTO `module` VALUES (1, 'add');
INSERT INTO `module` VALUES (2, 'delete');
INSERT INTO `module` VALUES (3, 'query');
INSERT INTO `module` VALUES (4, 'update');

-- ----------------------------
-- Table structure for module_role
-- ----------------------------
DROP TABLE IF EXISTS `module_role`;
CREATE TABLE `module_role`  (
  `rid` int(11) NULL DEFAULT NULL,
  `mid` int(11) NULL DEFAULT NULL,
  INDEX `rid`(`rid`) USING BTREE,
  INDEX `mid`(`mid`) USING BTREE,
  CONSTRAINT `mid` FOREIGN KEY (`mid`) REFERENCES `module` (`mid`) ON DELETE RESTRICT ON UPDATE RESTRICT,
  CONSTRAINT `rid` FOREIGN KEY (`rid`) REFERENCES `role` (`rid`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

-- ----------------------------
-- Records of module_role
-- ----------------------------
INSERT INTO `module_role` VALUES (1, 1);
INSERT INTO `module_role` VALUES (1, 2);
INSERT INTO `module_role` VALUES (1, 3);
INSERT INTO `module_role` VALUES (1, 4);
INSERT INTO `module_role` VALUES (2, 1);
INSERT INTO `module_role` VALUES (2, 3);

-- ----------------------------
-- Table structure for role
-- ----------------------------
DROP TABLE IF EXISTS `role`;
CREATE TABLE `role`  (
  `rid` int(11) NOT NULL AUTO_INCREMENT,
  `rname` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`rid`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

-- ----------------------------
-- Records of role
-- ----------------------------
INSERT INTO `role` VALUES (1, 'admin');
INSERT INTO `role` VALUES (2, 'customer');
INSERT INTO `role` VALUES (3, NULL);

-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (
  `uid` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`uid`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, 'hlhdidi', '123');
INSERT INTO `user` VALUES (2, 'xyycici', '1992');
INSERT INTO `user` VALUES (3, 'sujin', '123');

-- ----------------------------
-- Table structure for user_role
-- ----------------------------
DROP TABLE IF EXISTS `user_role`;
CREATE TABLE `user_role`  (
  `uid` int(11) NULL DEFAULT NULL,
  `rid` int(11) NULL DEFAULT NULL,
  INDEX `u_fk`(`uid`) USING BTREE,
  INDEX `r_fk`(`rid`) USING BTREE,
  CONSTRAINT `r_fk` FOREIGN KEY (`rid`) REFERENCES `role` (`rid`) ON DELETE RESTRICT ON UPDATE RESTRICT,
  CONSTRAINT `u_fk` FOREIGN KEY (`uid`) REFERENCES `user` (`uid`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

-- ----------------------------
-- Records of user_role
-- ----------------------------
INSERT INTO `user_role` VALUES (1, 1);
INSERT INTO `user_role` VALUES (2, 2);
INSERT INTO `user_role` VALUES (3, 3);

SET FOREIGN_KEY_CHECKS = 1;

当新添加一个用户时,只需要配置权限即可,module_role表中已经配置了什么权限拥有什么样的功能

SELECT u.*,r.*,m.* FROM user u inner join user_role ur on ur.uid=u.uid
        inner join role r on r.rid=ur.rid
        inner join module_role mr on mr.rid=r.rid
        inner join module m on mr.mid=m.mid
        WHERE username='hlhdidi'; -- xyycici用户已分配只要两个权限 add和query

2.pom.xml中添加Springboot集成shiro的相关依赖

<!-- shiro整合springboot所需相关依赖-->
	<dependency>
		<groupId>org.apache.shiro</groupId>
		<artifactId>shiro-spring</artifactId>
		<version>1.2.5</version>
	</dependency>
	<dependency>
		<groupId>org.apache.shiro</groupId>
		<artifactId>shiro-ehcache</artifactId>
		<version>1.2.5</version>
	</dependency>
	<dependency>
		<groupId>com.github.theborakompanioni</groupId>
		<artifactId>thymeleaf-extras-shiro</artifactId>
		<version>1.2.1</version>
	</dependency>
<!--end.......-->

3.创建实体类

仅列出关键实体类,其他实体类无需改动

用户 

package com.king.s5.model;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
//用户
public class User implements Serializable{
    private Integer uid;

    private String username;

    private String password;

    private Set<Role> roles = new HashSet<>();


    public User(Integer uid, String username, String password) {
        this.uid = uid;
        this.username = username;
        this.password = password;
    }

    public User() {
        super();
    }

    public Integer getUid() {
        return uid;
    }

    public void setUid(Integer uid) {
        this.uid = uid;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Set<Role> getRoles() {
        return roles;
    }

    public void setRoles(Set<Role> roles) {
        this.roles = roles;
    }
}

功能 

package com.king.s5.model;

import java.util.HashSet;
import java.util.Set;
//功能
public class Module {
    private Integer mid;

    private String mname;

    private Set<Role> roles;

    public Module(Integer mid, String mname) {
        this.mid = mid;
        this.mname = mname;
    }

    public Module() {
        super();
    }

    public Integer getMid() {
        return mid;
    }

    public void setMid(Integer mid) {
        this.mid = mid;
    }

    public String getMname() {
        return mname;
    }

    public void setMname(String mname) {
        this.mname = mname;
    }

    public Set<Role> getRoles() {
        return roles;
    }

    public void setRoles(Set<Role> roles) {
        this.roles = roles;
    }
}

权限

public class Role {
    private Integer rid;

    private String rname;

    private Set<User> users = new HashSet<>();
    private Set<Module> Modules = new HashSet<>();

    public Role(Integer rid, String rname) {
        this.rid = rid;
        this.rname = rname;
    }

    public Role() {
        super();
    }

    public Integer getRid() {
        return rid;
    }

    public void setRid(Integer rid) {
        this.rid = rid;
    }

    public String getRname() {
        return rname;
    }

    public void setRname(String rname) {
        this.rname = rname;
    }

    public Set<User> getUsers() {
        return users;
    }

    public void setUsers(Set<User> users) {
        this.users = users;
    }

    public Set<Module> getModules() {
        return Modules;
    }

    public void setModules(Set<Module> modules) {
        Modules = modules;
    }
}

4.编写持久层mapper.xml 

userMapper.xml,本次只写到mapper层,不做service层(仅列出关键mapper.xml),其他xml无需改变

<?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.king.s5.mapper.UserMapper" >
  <resultMap id="BaseResultMap" type="com.king.s5.model.User" >
    <constructor >
      <idArg column="uid" jdbcType="INTEGER" javaType="java.lang.Integer" />
      <arg column="username" jdbcType="VARCHAR" javaType="java.lang.String" />
      <arg column="password" jdbcType="VARCHAR" javaType="java.lang.String" />
    </constructor>
  </resultMap>
  <resultMap type="com.king.s5.model.User" id="userMap">
    <id property="uid" column="uid"/>
    <result property="username" column="username"/>
    <result property="password" column="password"/>
    <collection property="roles" ofType="com.king.s5.model.Role">
      <id property="rid" column="rid"/>
      <result property="rname" column="rname"/>
      <collection property="modules" ofType="com.king.s5.model.Module">
        <id property="mid" column="mid"/>
        <result property="mname" column="mname"/>
      </collection>
    </collection>
  </resultMap>
  <sql id="Base_Column_List" >
    uid, username, password
  </sql>
  <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
    select 
    <include refid="Base_Column_List" />
    from user
    where uid = #{uid,jdbcType=INTEGER}
  </select>
  <select id="queryUserName" parameterType="string" resultMap="userMap">
        SELECT u.*,r.*,m.* FROM user u inner join user_role ur on ur.uid=u.uid
        inner join role r on r.rid=ur.rid
        inner join module_role mr on mr.rid=r.rid
        inner join module m on mr.mid=m.mid
        WHERE username=#{username};
    </select>
  <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer" >
    delete from user
    where uid = #{uid,jdbcType=INTEGER}
  </delete>
  <insert id="insert" parameterType="com.king.s5.model.User" >
    insert into user (uid, username, password
      )
    values (#{uid,jdbcType=INTEGER}, #{username,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR}
      )
  </insert>
  <insert id="insertSelective" parameterType="com.king.s5.model.User" >
    insert into user
    <trim prefix="(" suffix=")" suffixOverrides="," >
      <if test="uid != null" >
        uid,
      </if>
      <if test="username != null" >
        username,
      </if>
      <if test="password != null" >
        password,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides="," >
      <if test="uid != null" >
        #{uid,jdbcType=INTEGER},
      </if>
      <if test="username != null" >
        #{username,jdbcType=VARCHAR},
      </if>
      <if test="password != null" >
        #{password,jdbcType=VARCHAR},
      </if>
    </trim>
  </insert>
  <update id="updateByPrimaryKeySelective" parameterType="com.king.s5.model.User" >
    update user
    <set >
      <if test="username != null" >
        username = #{username,jdbcType=VARCHAR},
      </if>
      <if test="password != null" >
        password = #{password,jdbcType=VARCHAR},
      </if>
    </set>
    where uid = #{uid,jdbcType=INTEGER}
  </update>
  <update id="updateByPrimaryKey" parameterType="com.king.s5.model.User" >
    update user
    set username = #{username,jdbcType=VARCHAR},
      password = #{password,jdbcType=VARCHAR}
    where uid = #{uid,jdbcType=INTEGER}
  </update>
</mapper>

moduleMapper.xml

<?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.king.s5.mapper.ModuleMapper" >
  <resultMap id="BaseResultMap" type="com.king.s5.model.Module" >
    <constructor >
      <idArg column="mid" jdbcType="INTEGER" javaType="java.lang.Integer" />
      <arg column="mname" jdbcType="VARCHAR" javaType="java.lang.String" />
    </constructor>
  </resultMap>
  <sql id="Base_Column_List" >
    mid, mname
  </sql>
  <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
    select 
    <include refid="Base_Column_List" />
    from module
    where mid = #{mid,jdbcType=INTEGER}
  </select>
  <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer" >
    delete from module
    where mid = #{mid,jdbcType=INTEGER}
  </delete>
  <insert id="insert" parameterType="com.king.s5.model.Module" >
    insert into module (mid, mname)
    values (#{mid,jdbcType=INTEGER}, #{mname,jdbcType=VARCHAR})
  </insert>
  <insert id="insertSelective" parameterType="com.king.s5.model.Module" >
    insert into module
    <trim prefix="(" suffix=")" suffixOverrides="," >
      <if test="mid != null" >
        mid,
      </if>
      <if test="mname != null" >
        mname,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides="," >
      <if test="mid != null" >
        #{mid,jdbcType=INTEGER},
      </if>
      <if test="mname != null" >
        #{mname,jdbcType=VARCHAR},
      </if>
    </trim>
  </insert>
  <update id="updateByPrimaryKeySelective" parameterType="com.king.s5.model.Module" >
    update module
    <set >
      <if test="mname != null" >
        mname = #{mname,jdbcType=VARCHAR},
      </if>
    </set>
    where mid = #{mid,jdbcType=INTEGER}
  </update>
  <update id="updateByPrimaryKey" parameterType="com.king.s5.model.Module" >
    update module
    set mname = #{mname,jdbcType=VARCHAR}
    where mid = #{mid,jdbcType=INTEGER}
  </update>
</mapper>

5.添加shiro的工具类

认证授权工具类

package com.king.s5.shiro;

import com.king.s5.biz.IUserBiz;
import com.king.s5.mapper.UserMapper;
import com.king.s5.model.Module;
import com.king.s5.model.Role;
import com.king.s5.model.User;
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.springframework.beans.factory.annotation.Autowired;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

public class AuthRealm extends AuthorizingRealm {

    @Autowired
    private UserMapper userMapper;

    //认证.登录
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        UsernamePasswordToken utoken=(UsernamePasswordToken) token;//获取用户输入的token
        String username = utoken.getUsername();
        User user = userMapper.queryUserName(username);
        //放入shiro.调用CredentialsMatcher检验密码
        return new SimpleAuthenticationInfo(user, user.getPassword(),this.getClass().getName());
    }
    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {
        //获取session中的用户
        User user=(User) principal.fromRealm(this.getClass().getName()).iterator().next();
        List<String> permissions=new ArrayList<>();
        Set<Role> roles = user.getRoles();
        if(roles.size()>0) {
            for(Role role : roles) {
                Set<Module> modules = role.getModules();
                if(modules.size()>0) {
                    for(Module module : modules) {
                        permissions.add(module.getMname());
                    }
                }
            }
        }
        SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
        //将权限放入shiro中.
        info.addStringPermissions(permissions);
        return info;
    }
}

权限用户密码校验类

package com.king.s5.shiro;

import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.SimpleCredentialsMatcher;

public class CredentialsMatcher extends SimpleCredentialsMatcher {

    //校验
    @Override
    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
        UsernamePasswordToken utoken=(UsernamePasswordToken) token;
        //获得用户输入的密码:(可以采用加盐(salt)的方式去检验)
        String inPassword = new String(utoken.getPassword());
        //获得数据库中的密码
        String dbPassword=(String) info.getCredentials();
        //进行密码的比对
        return this.equals(inPassword, dbPassword);
    }
}

shiro配置类

package com.king.s5.shiro;

import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.mgt.SecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;

/**
 * shiro的配置类
 * @author sujin
 *
 */
@Configuration
public class ShiroConfiguration {
    @Bean(name="shiroFilter")
    public ShiroFilterFactoryBean shiroFilter(@Qualifier("securityManager") SecurityManager manager) {
        ShiroFilterFactoryBean bean=new ShiroFilterFactoryBean();
        bean.setSecurityManager(manager);
        //配置登录的url和登录成功的url
        bean.setLoginUrl("/login");
        bean.setSuccessUrl("/home");
        //配置访问权限
        LinkedHashMap<String, String> filterChainDefinitionMap=new LinkedHashMap<>();
        filterChainDefinitionMap.put("/login*", "anon"); //表示可以匿名访问
        filterChainDefinitionMap.put("/loginUser", "anon");
        filterChainDefinitionMap.put("/client/test", "anon");
        filterChainDefinitionMap.put("/assert/test", "anon");//添加白名单
        filterChainDefinitionMap.put("/assert/get", "anon");//添加白名单
        filterChainDefinitionMap.put("/assert/assertQuery", "anon");//添加白名单
        filterChainDefinitionMap.put("/a", "anon");
        filterChainDefinitionMap.put("/book/list", "anon");
        filterChainDefinitionMap.put("/logout*","anon");
        filterChainDefinitionMap.put("/jsp/error.jsp*","anon");
        filterChainDefinitionMap.put("/jsp/login.jsp*","authc");
        filterChainDefinitionMap.put("/*", "authc");//表示需要认证才可以访问
        filterChainDefinitionMap.put("/**", "authc");//表示需要认证才可以访问
        filterChainDefinitionMap.put("/*.*", "authc");
        bean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return bean;
    }
    //配置核心安全事务管理器
    @Bean(name="securityManager")
    public SecurityManager securityManager(@Qualifier("authRealm") AuthRealm authRealm) {
        System.err.println("--------------shiro已经加载----------------");
        DefaultWebSecurityManager manager=new DefaultWebSecurityManager();
        manager.setRealm(authRealm);
        return manager;
    }
    //配置自定义的权限登录器
    @Bean(name="authRealm")
    public AuthRealm authRealm(@Qualifier("credentialsMatcher") CredentialsMatcher matcher) {
        AuthRealm authRealm=new AuthRealm();
        authRealm.setCredentialsMatcher(matcher);
        return authRealm;
    }
    //配置自定义的密码比较器
    @Bean(name="credentialsMatcher")
    public CredentialsMatcher credentialsMatcher() {
        return new CredentialsMatcher();
    }
    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor(){
        return new LifecycleBeanPostProcessor();
    }
    @Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator(){
        DefaultAdvisorAutoProxyCreator creator=new DefaultAdvisorAutoProxyCreator();
        creator.setProxyTargetClass(true);
        return creator;
    }
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager") SecurityManager manager) {
        AuthorizationAttributeSourceAdvisor advisor=new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(manager);
        return advisor;
    }
}

6.控制层controller

package com.king.s5.controller;

import com.king.s5.model.User;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpSession;

@Controller
public class LoginController {
    @RequestMapping("/login")
    public String login() {
        return "login";
    }

    @RequestMapping("/a")
    public String a() {
        return "a";
    }

    @RequestMapping("/loginUser")
    public String loginUser(String username,String password,HttpSession session) {
        //授权认证
        UsernamePasswordToken usernamePasswordToken=new UsernamePasswordToken(username,password);
        Subject subject = SecurityUtils.getSubject();
        try {
            //完成登录
            subject.login(usernamePasswordToken);
            //获得用户对象
            User user=(User) subject.getPrincipal();
            //存入session
            session.setAttribute("user", user);
            return "index";
        } catch(Exception e) {
            return "login";//返回登录页面
        }

    }
    @RequestMapping("/logOut")
    public String logOut(HttpSession session) {
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
//        session.removeAttribute("user");
        return "login";
    }
}

7.视图层jsp

login.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html lang="en">
<head>
    <title>登录</title>
</head>

<h1>欢迎登录!${user.username }</h1>
<form action="${pageContext.request.contextPath }/loginUser" method="post">
    <input type="text" name="username"><br>
    <input type="password" name="password"><br>
    <input type="submit" value="提交">
</form>
</body>
</html>

index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8" %>
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
<!DOCTYPE html>
<html lang="en">
<head>
    <title>登录</title>
</head>

<h1>欢迎${user.username }光临!请选择你的操作:</h1><br>
<ul>
    <shiro:hasPermission name="add"><li>增加</li></shiro:hasPermission>
    <shiro:hasPermission name="delete"><li>删除</li></shiro:hasPermission>
    <shiro:hasPermission name="update"><li>修改</li></shiro:hasPermission>
    <shiro:hasPermission name="query"><li>查询</li></shiro:hasPermission>

</ul>
<a href="${pageContext.request.contextPath }/logOut">点我注销</a>
</body>
</html>

8.shiro标签的使用

guest标签 验证当前用户是否为“访客”,即未认证(包含未记住)的用户 
user标签认证通过或已记住的用户
authenticated标签已认证通过的用户。不包含已记住的用户,这是与user标签的区别所在
notAuthenticated标签未认证通过用户,与authenticated标签相对应。与guest标签的区别是,该标签包含已记住用户
principal 标签输出当前用户信息,通常为登录帐号信息
hasRole标签验证当前用户是否属于该角色
lacksRole标签与hasRole标签逻辑相反,当用户不属于该角色时验证通过
hasAnyRole标签验证当前用户是否属于以下任意一个角色
hasPermission标签验证当前用户是否拥有指定权限
lacksPermission标签与hasPermission标签逻辑相反,当前用户没有制定权限时,验证通过

如果大家有什么问题,可以在下方留言,想要源码的可以到我的资源库下载    点击下载 

 

--------------如果大家喜欢我的博客,可以点击左上角的关注哦。

  • 17
    点赞
  • 95
    收藏
    觉得还不错? 一键收藏
  • 165
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 165
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值