springboot+shiro+jwt整合实现权限认证

前言

源码获取方式在最下面或直接加v: 13357214920
shiro

我前面文章有就不多介绍了. 传送门==>https://blog.csdn.net/Ambitiouss/article/details/111469787?spm=1001.2014.3001.5501他是一个可独立运行的权限控制框架,也能很方便的和其他框架集成。

jwt

我认为jwt就是用来解决session单点登录和解决跨域问题的一个东西<这里我就不细说这些了,网上太多了>。
以下内容摘抄自网络。

Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。

shiro+jwt流程说明:

1.写一个拦截器,看是否带了token,如果没带则认为是登录请求。直接放过,否则进入认证流程。
2.根据用户名查找该用户是否存在, 然后给密码加盐在比对密码,如果正确,则流程结束,返回token,否则就爱怎么回复怎么回复用户。
3.此时已经获取token,则前端每次请求必须带上token,后端在检测有token时去验证token是否正确,如果正确则进入shiro域去认证授权。

整合开始

一个用户多个角色 一个角色多个权限菜单。
数据表实现

表中文名 表名称
用户表 t_user
角色表 t_role
用户角色表 t_user_role
菜单表 t_menu
角色菜单表 t_role_menu
/* 用户表 */
CREATE TABLE IF NOT EXISTS t_user
(
	id 		VARCHAR(32) NOT NULL COMMENT '用户id	',			/* 主键,用户id			*/
	userName 	 VARCHAR(64) NOT NULL COMMENT '账号名',			/* 账号名				*/
	password VARCHAR(64) NOT NULL COMMENT '密码',				/* 密码(加密后)			*/
	personName VARCHAR(32) DEFAULT '' COMMENT '账号使用者',		/* 账号使用者名称		*/
	idNumber VARCHAR(32) DEFAULT '' COMMENT '证件号码',			/* 证件号码				*/
	telphone VARCHAR(32) DEFAULT '' COMMENT '联系号码',			/* 联系号码				*/
	loginWay TINYINT DEFAULT 0 COMMENT '登录方式',				/* 登录方式				*/
	score   FLOAT   DEFAULT 5 COMMENT '用户评分',                 /* 用户评分				*/
	enabled TINYINT DEFAULT 1 COMMENT '是否认证启用',				/* 是否启用				*/
	expired TINYINT DEFAULT 0 COMMENT '是否失效',				/* 是否失效 			*/
	locked 	TINYINT DEFAULT 0 COMMENT '是否锁定',				/* 是否锁定 			*/
	createTime datetime default now() COMMENT '创建时间',        /* 创建时间 			*/
	PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户信息 ';

-- 初始化数据
INSERT INTO `house`.`t_user` (`id`, `userName`, `password`, `personName`, `idNumber`, `telphone`, `loginWay`, `enabled`, `expired`, `locked`, `createTime`) VALUES ('1', 'YWRtaW4=', 'fe3ca4c5097cd9f957b61f9d65035b6c', 'admin', '43052319981221071X', '13357214920', '0', '1', '0', '0', '2021-06-11 16:49:18');
INSERT INTO `house`.`t_user` (`id`, `userName`, `password`, `personName`, `idNumber`, `telphone`, `loginWay`, `score`, `enabled`, `expired`, `locked`, `createTime`) VALUES ('2', 'dHdq', 'MTIzNDU2', 'admin', '43052319981221071X', '13357214920', '0', '5', '1', '0', '0', '2021-07-15 16:17:34');


/* 角色表*/
CREATE TABLE IF NOT EXISTS t_role
(
	id 		VARCHAR(32) NOT NULL COMMENT '角色id',			/* 主键,角色id			*/
	name 	VARCHAR(64) NOT NULL COMMENT '名称',			/* 角色名称				*/
	roleKey VARCHAR(32) NOT NULL COMMENT '角色key',
	level  TINYINT COMMENT '用户级别',						/* 用户级别			*/
	status TINYINT DEFAULT 0 COMMENT '状态',				/* 状态 启用、禁止		*/
	remark	VARCHAR(128) DEFAULT '' COMMENT '描述',			/* 描述					*/
	PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='角色信息 ';

-- 初始化数据
INSERT INTO `house`.`t_role` (`id`, `name`, `roleKey`, `level`, `status`, `remark`) VALUES ('1', '超级管理员', 'superAdmin', '1', '0', '超级管理员拥有平台所有权限');
INSERT INTO `house`.`t_role` (`id`, `name`, `roleKey`, `level`, `status`, `remark`) VALUES ('2', '管理员', 'admin', '2', '0', '系统管理员,除去添加管理员、查看日志和修改超级管理员信息功能外拥有平台所有权限');
INSERT INTO `house`.`t_role` (`id`, `name`, `roleKey`, `level`, `status`, `remark`) VALUES ('3', '房东', 'landlord', '3', '0', '房东能添加房子,和修改自己房子的配套信息');
INSERT INTO `house`.`t_role` (`id`, `name`, `roleKey`, `level`, `status`, `remark`) VALUES ('4', '普通用户', 'user', '4', '0', '普通用户拥有查看、预约和评价房子与工作人员');

/* 用户-角色中间表*/
CREATE TABLE IF NOT EXISTS t_user_role
(
	id 		VARCHAR(32) NOT NULL COMMENT 'id',				/* 主键id			*/
	userId 	VARCHAR(32) NOT NULL COMMENT '用户',			/* 用户id COMMENT '',用户表外键			*/
	roleId 	VARCHAR(32) NOT NULL COMMENT '角色',			/* 角色id COMMENT '',角色表外键			*/
	PRIMARY KEY (id),
	FOREIGN KEY(userId) REFERENCES t_user(id)  ON DELETE CASCADE ON UPDATE CASCADE,
	FOREIGN KEY(roleId) REFERENCES t_role(id)  ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户-角色中间表 ';
-- 初始化数据
INSERT INTO `house`.`t_user_role` (`id`, `userId`, `roleId`) VALUES ('1', '1', '1');
INSERT INTO `house`.`t_user_role` (`id`, `userId`, `roleId`) VALUES ('2', '2', '2');
INSERT INTO `house`.`t_user_role` (`id`, `userId`, `roleId`) VALUES ('3', '1', '2');



/* 菜单表 */
CREATE TABLE IF NOT EXISTS t_menu
(
    id 		VARCHAR(32) NOT NULL COMMENT 'id',				                        /* 主键id			*/
    name    VARCHAR(32) NOT NULL COMMENT '菜单名称',                                 /*  菜单名称          */
    folderOrMenu  BIGINT(4) NOT NULL DEFAULT 0 COMMENT '是目录还是菜单 0目录 1菜单',  /*  是目录还是菜单  0目录 1菜单   */
    menuHref VARCHAR(256)         COMMENT '菜单链接',                               /*  菜单链接          */
    menuRoute    VARCHAR(128)  COMMENT '菜单路由',                                /*  菜单路由          */
    menuLevel       BIGINT(4)     COMMENT '菜单排序',                               /*  菜单排序          */
    status          BIGINT(2) NOT NULL DEFAULT 0   COMMENT '是否停用',              /*  是否停用 0 正常 1 停用 */
    remark    VARCHAR(256)        COMMENT '备注',                                  /*  备注 */
    parentId  VARCHAR(16)        COMMENT '父菜单目录id',                              /*  父菜单目录id */
    permissionName  VARCHAR(32) NOT NULL COMMENT'菜单权限名称',                            /* 菜单权限名称 */
    reserve1  VARCHAR(128)        COMMENT '备用字段1',                               /*  备用字段1 */
    PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='菜单资源表 ';
INSERT INTO `house`.`t_menu` (`id`, `name`, `folderOrMenu`, `menuHref`, `menuRoute`, `menuLevel`, `status`, `remark`, `parentId`, `permissionName`, `reserve1`) VALUES ('1', '系统管理', '0', 'system', 'system', '0', '0', '系统管理', NULL, 'system', NULL);
INSERT INTO `house`.`t_menu` (`id`, `name`, `folderOrMenu`, `menuHref`, `menuRoute`, `menuLevel`, `status`, `remark`, `parentId`, `permissionName`, `reserve1`) VALUES ('2', '用户管理', '1', 'userMange', 'system/userMange', '1', '0', '用户管理', '1', 'system-user', NULL);
INSERT INTO `house`.`t_menu` (`id`, `name`, `folderOrMenu`, `menuHref`, `menuRoute`, `menuLevel`, `status`, `remark`, `parentId`, `permissionName`, `reserve1`) VALUES ('3', '角色管理', '2', 'roleMange', 'system/roleMange', '2', '0', '角色管理', '1', 'system-role', NULL);
INSERT INTO `house`.`t_menu` (`id`, `name`, `folderOrMenu`, `menuHref`, `menuRoute`, `menuLevel`, `status`, `remark`, `parentId`, `permissionName`, `reserve1`) VALUES ('4', '菜单管理', '3', 'menuMange', 'system/menuMange', '3', '0', '菜单管理', '1', 'system-menu', NULL);
INSERT INTO `house`.`t_menu` (`id`, `name`, `folderOrMenu`, `menuHref`, `menuRoute`, `menuLevel`, `status`, `remark`, `parentId`, `permissionName`, `reserve1`) VALUES ('5', '系统日志', '4', 'operateLog', 'system/operate', '4', '0', '系统日志', '1', 'system-log', NULL);



/* 角色菜单 */
CREATE TABLE IF NOT EXISTS t_role_menu
(
    id  VARCHAR(32) NOT NULL COMMENT 'id',
    roleId VARCHAR(32) NOT NULL COMMENT '角色id',
    menuId VARCHAR(32) NOT NULL COMMENT '菜单id',
    PRIMARY KEY (id),
	FOREIGN KEY(roleId) REFERENCES t_role(id)  ON DELETE CASCADE ON UPDATE CASCADE,
	FOREIGN KEY(menuId) REFERENCES t_menu(id)  ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='角色菜单中间表 ';
INSERT INTO `house`.`t_role_menu` (`id`, `roleId`, `menuId`) VALUES ('1', '1', '1');
INSERT INTO `house`.`t_role_menu` (`id`, `roleId`, `menuId`) VALUES ('2', '1', '2');
INSERT INTO `house`.`t_role_menu` (`id`, `roleId`, `menuId`) VALUES ('3', '1', '3');
INSERT INTO `house`.`t_role_menu` (`id`, `roleId`, `menuId`) VALUES ('4', '1', '4');
INSERT INTO `house`.`t_role_menu` (`id`, `roleId`, `menuId`) VALUES ('5', '1', '5');
INSERT INTO `house`.`t_role_menu` (`id`, `roleId`, `menuId`) VALUES ('6', '2', '1');
INSERT INTO `house`.`t_role_menu` (`id`, `roleId`, `menuId`) VALUES ('7', '2', '2');
INSERT INTO `house`.`t_role_menu` (`id`, `roleId`, `menuId`) VALUES ('8', '2', '3');
INSERT INTO `house`.`t_role_menu` (`id`, `roleId`, `menuId`) VALUES ('9', '2', '4');

pom.xml


<dependency>
    <groupId>org.apache.shirogroupId>
    <artifactId>shiro-springartifactId>
    <version>1.4.0version>
dependency>
<dependency>
    <groupId>org.apache.shirogroupId>
    <artifactId>shiro-webartifactId>
    <version>1.4.0version>
dependency>

<dependency>
    <groupId>com.auth0groupId>
    <artifactId>java-jwtartifactId>
    <version>3.2.0version>
dependency>
<dependency>
    <groupId>io.jsonwebtokengroupId>
    <artifactId>jjwtartifactId>
    <version>0.9.1version>
dependency>
<dependency>
    <groupId>javax.xml.bindgroupId>
    <artifactId>jaxb-apiartifactId>
    <version>2.3.0version>
dependency>

配置shiro

package com.wenjun.shiro;

import com.wenjun.Filter.JWTFilter;
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
import org.apache.shiro.mgt.DefaultSubjectDAO;
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.mgt.SecurityManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
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 javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @author wen jun tang
 */
@Configuration
public class ShiroConfig {

    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
        // shiro内置过滤器
        /**
         * anon: 无需认证直接访问
         * authc: 必须认证才能访问
         * user: 必须拥有记住我功能才能用
         * perms: 拥有某个资源权限才能用
         * role: 拥有某个角色权限才能用
         */
        // 添加自己的过滤器并且取名为jwt
        Map<String, Filter> filterMap = new LinkedHashMap<>();
        // 设置我们自定义的JWT过滤器
        filterMap.put("jwt", new JWTFilter());
        factoryBean.setFilters(filterMap);
        factoryBean.setSecurityManager(securityManager);
        // 设置无权限时跳转的 url;
        factoryBean.setUnauthorizedUrl("/unauthorized/无权限");
        Map<String, String> filterRuleMap = new HashMap<>(100);
        // 所有请求通过我们自己的JWT Filter
        filterRuleMap.put("/**", "jwt");

        // 放行不需要权限认证的接口
        filterRuleMap.put("/user/login", "anon");
        filterRuleMap.put("/user/getVerificationCode", "anon");

        //放行Swagger接口
        filterRuleMap.put("/v2/api-docs","anon");
        filterRuleMap.put("/swagger-resources/configuration/ui","anon");
        filterRuleMap.put("/swagger-resources","anon");
        filterRuleMap.put("/swagger-resources/configuration/security","anon");
        filterRuleMap.put("/swagger-ui.html","anon");
        filterRuleMap.put("/webjars/**","anon");

        factoryBean.setFilterChainDefinitionMap(filterRuleMap);
        return factoryBean;
    }


    /**
     * 注入 securityManager
     */
    @Bean
    public DefaultWebSecurityManager  securityManager(CustomRealm customRealm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        // 设置自定义 realm.
        securityManager.setRealm(customRealm);

        /*
         * 关闭shiro自带的session
         */
        DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
        DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();
        defaultSessionStorageEvaluator.setSessionStorageEnabled(false);
        subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);
        securityManager.setSubjectDAO(subjectDAO);

        return securityManager;
    }

    /**
     * 添加注解支持
     */
    @Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        // 强制使用cglib,防止重复代理和可能引起代理出错的问题
        defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
        return defaultAdvisorAutoProxyCreator;
    }

    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        return advisor;
    }

    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

}

配置shiro域

package com.wenjun.shiro;

import com.wenjun.busines.system.mapper.UserMapper;
import com.wenjun.busines.system.pojo.Menu;
import com.wenjun.busines.system.pojo.Role;
import com.wenjun.busines.system.pojo.User;
import com.wenjun.busines.system.service.IMenuService;
import com.wenjun.busines.system.service.IRoleService;
import com.wenjun.util.CheckUtil;
import com.wenjun.util.JWTUtil;
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.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;

/**
 * @projectName: house
 * @package: com.wenjun.shiro
 * @className: CustomRealm
 * @author: wen jun tang
 * @description: 自定义域,实现shiro安全认证
 * @date: 2021年07月14日 15:57
 * @version: 1.0
 */
@Component
public class CustomRealm extends AuthorizingRealm {

    @Resource
    private UserService userService;
    @Resource
    private IRoleService iRoleService;
    @Resource
    private IMenuService iMenuService;
    /**
     * 必须重写此方法,不然会报错
     */
    @Override
    public boolean supports(AuthenticationToken  token) {
        return token instanceof JWTToken;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("doGetAuthenticationInfo=> 认证");
        String token = (String) authenticationToken.getCredentials();
        // 解密获得username,用于和数据库进行对比
        String username = JWTUtil.getUsername(token);
        if (username == null || !JWTUtil.verify(token, username)) {
            throw new AuthenticationException("token认证失败!");
        }

        /* 以下数据库查询可根据实际情况,可以不必再次查询,这里我两次查询会很耗资源
         * 我这里增加两次查询是因为考虑到数据库管理员可能自行更改数据库中的用户信息
         */
        User user = userService.findByPersonName(username);
        if (CheckUtil.isNull(user.getPassword())) {
            throw new AuthenticationException("该用户不存在!");
        }

        if (user.getLocked() == 1) {
            throw new AuthenticationException("该用户已被封号!");
        }

        return new SimpleAuthenticationInfo(token, token, "MyRealm");
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        System.out.println("doGetAuthorizationInfo=>> 授权");
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        // 获取用户id
        String userId = JWTUtil.getUserId(ServletHttpRequest.getToken(
                ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest()
        ));
        List<Role> roles = iRoleService.findByUserId(userId);
        Set<String> roleSet = new HashSet<>();
        Set<String> permissions = new HashSet<>();
        for (Role role : roles) {
            // 查找该角色权限
            List<Menu> menus = iMenuService.findByRoleId(role.getId());
            role.setRoleMenu(menus);
            // 需要将 [role], [permission] 封装到 Set 作为 info.setRoles(), info.setStringPermissions() 的参数
            roleSet.add(role.getRoleKey());
            for (Menu menu : menus) {
                permissions.add(menu.getPermissionName());
            }
        }

        // 设置用户[角色]和[权限]
        info.setRoles(roleSet);
        info.setStringPermissions(permissions);

        return info;
    }
}

扩张token

package com.wenjun.shiro;

import org.apache.shiro.authc.AuthenticationToken;

/**
 * @projectName: house
 * @package: com.wenjun.shiro
 * @className: JWTToken
 * @author: wen jun tang
 * @description: 对token进行扩展
 * @date: 2021年07月14日 15:59
 * @version: 1.0
 */
public class JWTToken implements AuthenticationToken {

    private String token;

    public JWTToken(String token) {
        this.token = token;
    }

    @Override
    public Object getPrincipal() {
        return token;
    }

    @Override
    public Object getCredentials() {
        return token;
    }
}

生成token工具类

package com.wenjun.util;

import com.auth0.jwt.exceptions.JWTDecodeException;
import io.jsonwebtoken.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.Date;

/**
 * @projectName: house
 * @package: com.wenjun.util
 * @className: JWTUtil
 * @author: wen jun tang
 * @description: token生成工具类
 * @date: 2021年07月14日 16:04
 * @version: 1.0
 */
@Component
public class JWTUtil {

    /**
     * 密钥
     */
    private static String SECRET;

    @Value("${jwt.secret}")
    private void setSecretKey(String secret) {
        JWTUtil.SECRET = secret;
    }

    /**
     * 过期时间 24 小时
     */
    private static final long EXPIRE_TIME = 86400 * 1000;


    /**
     * 生成 token
     */
    public static String createToken(String username, String userId) {
        try {
            Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
            JwtBuilder jwtBuilder = Jwts.builder();
            // 附带username信息
            return jwtBuilder.setHeaderParam("type", "JWT")
                    // head
                    .setHeaderParam("alg", "HS256")
                    // payload
                    .claim("username", username)
                    .claim("userId", userId)
                    .setSubject("admin-house")
                    //到期时间
                    .setExpiration(date)
                    //创建一个新的JWT,并使用给定的算法进行标记
                    .setId(TextUtil.getUUID().toString())
                    // signature
                    .signWith(SignatureAlgorithm.HS256, SECRET)
                    .compact();
        } catch (Exception e) {
            return null;
        }
    }


    /**
     * 校验 token 是否正确
     */
    public static boolean verify(String token) {
        try {
            Jwts.parser()
                    .setSigningKey(SECRET)
                    .parseClaimsJws(token)
                    .getBody();
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 获得token中的信息,无需secret解密也能获得
     */
    public static String getUsername(String token) {
        try {
            JwtParser jwtParser = Jwts.parser();
            Jws<Claims> claimsJws = jwtParser.setSigningKey(SECRET).parseClaimsJws(token);
            Claims claims = claimsJws.getBody();

            return (String) claims.get("username");
        } catch (JWTDecodeException e) {
            return null;
        }
    }

    /**
     * 获得token中的信息,无需secret解密也能获得
     */
    public static String getUserId(String token) {
        try {
            JwtParser jwtParser = Jwts.parser();
            Jws<Claims> claimsJws = jwtParser.setSigningKey(SECRET).parseClaimsJws(token);
            Claims claims = claimsJws.getBody();

            return (String) claims.get("userId");
        } catch (JWTDecodeException e) {
            return null;
        }
    }
}


使用

package com.wenjun.busines.system.controller;

import com.wenjun.anno.Syslog;
import com.wenjun.busines.system.dto.LoginParam;
import com.wenjun.busines.system.pojo.AddUserParam;
import com.wenjun.busines.system.pojo.User;
import com.wenjun.busines.system.pojo.UserResources;
import com.wenjun.busines.system.pojo.UserRole;
import com.wenjun.busines.system.service.IUserRoleService;
import com.wenjun.busines.system.service.UserService;
import com.wenjun.handlerException.error.CommonEnum;
import com.wenjun.handlerException.error.ReturnValue;
import com.wenjun.redis.UserLoginService;
import com.wenjun.util.CheckUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;

/**
 * @projectName: house
 * @package: com.wenjun.busines.system.controller
 * @className: UserController
 * @author: wen jun tang
 * @description: 用户相关操作前端控制器
 * @date: 2021年07月14日 17:26
 * @version: 1.0
 */
@Slf4j
@RequestMapping("/user")
@RestController
@Api(value = "用户相关操作接口", tags = "用户相关操作接口")
public class UserController {
    @Resource
    private UserLoginService userLoginService;
    @Resource
    private UserService userService;
    @Resource
    private IUserRoleService iUserRoleService;

    public static final String RANDOMKEY = "randomCode";

    @GetMapping("/login")
    @ApiOperation(value="登录接口", notes="账号密码 随机数登录")
    @Syslog(module="用户信息",style="查询",description="账号密码 随机数登录")
    public ReturnValue<String> login(@Valid LoginParam loginParam) throws Exception {
        return new ReturnValue<>(CommonEnum.ERROR_SUCCESS, userService.findByUserName(loginParam));
    }

    @GetMapping("/getVerificationCode")
    @ApiOperation(value="获取随机码接口", notes="随机数接口")
    @Syslog(module="用户信息",style="查询",description="获取随机码")
    public ReturnValue<String> getVerificationCode() {
        userLoginService.delete(RANDOMKEY);
        userLoginService.setKey(RANDOMKEY, String.valueOf((int) ((Math.random() * 9 + 1) * 10000)), 60);

        return new ReturnValue<>(CommonEnum.ERROR_SUCCESS, userLoginService.getKey(RANDOMKEY));
    }

    @GetMapping("/getUserResources")
    @RequiresRoles(logical = Logical.OR, value = {"user", "landlord", "admin", "superAdmin"})
    @Syslog(module="用户信息",style="查询",description="查询用户角色权限信息")
    @ApiOperation(value="根据token获取用户角色权限信息接口", notes="根据token获取用户角色权限信息")
    public ReturnValue<UserResources> getUserResources(HttpServletRequest request) throws Exception {
        String header = request.getHeader("Authorization");
        if (CheckUtil.isNull(header) && !header.startsWith("Bearer ")) {
            throw new Exception(CommonEnum.ERROR_TOKEN.getDescription());
        }
        String token = header.substring(7);

        return new ReturnValue<>(userService.findByUserResource(token));
    }

    @PostMapping("/add")
    @RequiresRoles(logical = Logical.OR, value = {"user", "landlord", "admin", "superAdmin"})
    @Syslog(module="用户信息",style="新增",description="新增用户")
    @ApiOperation(value="新增用户信息接口", notes="新增用户信息接口")
    public ReturnValue<String> add(AddUserParam addUserParam) {
        userService.insert(addUserParam);

        return new ReturnValue<>(CommonEnum.ERROR_SUCCESS);
    }

    @PostMapping("/addUserRole")
    @RequiresRoles(logical = Logical.OR, value = {"admin", "superAdmin"})
    @Syslog(module="用户信息",style="新增",description="用户新增角色")
    @ApiOperation(value="用户新增角色接口", notes="用户新增角色接口")
    public ReturnValue<String> addUserRole(UserRole userRole) {
        iUserRoleService.add(userRole);

        return new ReturnValue<>(CommonEnum.ERROR_SUCCESS);
    }

    @DeleteMapping("/deleteUserRole")
    @RequiresRoles(logical = Logical.OR, value = {"superAdmin"})
    @Syslog(module="用户信息",style="删除",description="删除用户角色")
    @ApiOperation(value="删除用户角色接口", notes="删除用户角色接口")
    public ReturnValue<String> deleteUserRole(String userId, String roleId) {
        iUserRoleService.deleteByAttributes(userId, roleId);
        return new ReturnValue<>(CommonEnum.ERROR_SUCCESS);
    }

    @PutMapping("/update")
    @RequiresRoles(logical = Logical.OR, value = {"user", "landlord", "admin", "superAdmin"})
    @Syslog(module="用户信息",style="修改",description="修改用户信息")
    @ApiOperation(value="修改用户信息接口", notes="修改用户信息接口")
    public ReturnValue<String> updateUser(User user) {
        userService.update(user);

        return new ReturnValue<>(CommonEnum.ERROR_SUCCESS);
    }

    @DeleteMapping("/deleteUser")
    @RequiresRoles(logical = Logical.OR, value = {"superAdmin"})
    @Syslog(module="用户信息",style="删除",description="删除用户")
    @ApiOperation(value="删除用户", notes="删除用户")
    public ReturnValue<String> deleteUser(String userId) {
        userService.delete(userId);

        return new ReturnValue<>(CommonEnum.ERROR_SUCCESS);
    }
}

操作展示:
步骤:
1.获取随机码:
springboot+shiro+jwt整合实现权限认证_第1张图片

2.拿着随机码登录:
springboot+shiro+jwt整合实现权限认证_第2张图片
3.拿token在postmain配置好token

springboot+shiro+jwt整合实现权限认证_第3张图片
我们这里是全部角色都能查这个接口, 刚刚我们是超级管理员登录的
springboot+shiro+jwt整合实现权限认证_第4张图片

springboot+shiro+jwt整合实现权限认证_第5张图片
我们改一下,改成超级管理员和管理员不能查
springboot+shiro+jwt整合实现权限认证_第6张图片
springboot+shiro+jwt整合实现权限认证_第7张图片

源码获取方式: 给我的五个作品点赞+留言… 我验证会发你邮箱… 免费

你可能感兴趣的:(java,java)