gitee代码地址https://gitee.com/wufanlove/springboot-shiro-swagger-mybatisplus.git
在SpringBoot项目pom.xml文件中引入依赖
<dependency>
<groupId>io.springfoxgroupId>
<artifactId>springfox-swagger2artifactId>
<version>2.9.2version>
dependency>
<dependency>
<groupId>io.springfoxgroupId>
<artifactId>springfox-swagger-uiartifactId>
<version>2.9.2version>
dependency>
编写SwaggerConfig配置Swagger相关信息
import io.swagger.annotations.Api;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* @email: [email protected]
* @date: 2021/11/11 9:42
* 功能:
* 描述:
* @author: 吴帆
**/
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.useDefaultResponseMessages(false)
.apiInfo(webApiInfo())
.select()
.apis(RequestHandlerSelectors.withClassAnnotation(Api.class))
.paths(PathSelectors.any())
.build();
}
private ApiInfo webApiInfo(){
return new ApiInfoBuilder()
.title("接口文档")
.description("开发接口文档")
.version("1.0")
.contact(new Contact("我的git地址", "https://gitee.com/wufanlove", "[email protected]"))
.build();
}
}
注意:一定要开启@EnableSwagger2注解,apis(RequestHandlerSelectors.withClassAnnotation(Api.class))意思是只要类上面存在@Api注解的类都会被加载到swagger接口文档。
新建Controller测试类测试swagger文档是否生效
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @email: [email protected]
* @date: 2021/11/11 9:50
* 功能:
* 描述:
* @author: 吴帆
**/
@Api(tags = "swagger接口测试")
@RestController
@RequestMapping("/swagger")
public class SwaggerTestController {
@ApiOperation(value = "测试")
@PostMapping("/test")
public String test(){
return "swagger-test-success";
}
}
访问ip:端口/项目名称/swagger-ui.html地址查看接口文档信息如下则整合成功
引入Mybatis-Plus依赖
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-boot-starterartifactId>
<version>3.2.0version>
dependency>
引入数据库驱动
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<scope>runtimescope>
dependency>
配置数据信息
# 数据库驱动:
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# 数据库连接地址
spring.datasource.url=jdbc:mysql://192.168.147.135:3306/rbac?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&useSSL=true
# 数据库用户名&密码:
spring.datasource.username=root
spring.datasource.password=123456
自行变为自己实际的数据库相关信息
mybatis-plus相关简单配置
#mapper.xml文件存放位置
mybatis-plus.mapper-locations=classpath:/mapper/**/*.xml
#打印sql日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
#开启驼峰命名规则
mybatis-plus.configuration.map-underscore-to-camel-case=true
#逻辑删除
mybatis-plus.global-config.db-config.logic-delete-field=deleted
mybatis-plus.global-config.db-config.logic-delete-value=1
mybatis-plus.global-config.db-config.logic-not-delete-value=0
创建用户表
CREATE TABLE sys_user(
id BIGINT (15) NOT NULL AUTO_INCREMENT COMMENT '主键',
user_name VARCHAR (50) NOT NULL DEFAULT '' COMMENT '用户名称',
pass_word VARCHAR (50) NOT NULL DEFAULT '' COMMENT '密码',
salt VARCHAR (50) NOT NULL DEFAULT '' COMMENT '加密盐值',
deleted INT (11) NOT NULL DEFAULT -1 COMMENT '1逻辑已删除值,0逻辑未删除值',
create_time DATETIME NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '创建时间',
update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (id)
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT '用户表';
在SpringBoot项目中针对用户表建SysUser、SysUserMapper、SysUserMapper.xml、SysUserService、SysUserServiceImpl
新建SysUser 实体类
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
import java.util.Date;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @email: [email protected]
* @date: 2021/11/11 11:30
* 功能:
* 描述:
* @author: 吴帆
**/
/**
* 用户表
*/
@ApiModel(value = "com-hetaozi-login-entity-SysUser")
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@TableName(value = "sys_user")
public class SysUser implements Serializable {
/**
* 主键
*/
@TableId(value = "id", type = IdType.AUTO)
@ApiModelProperty(value = "主键")
private Long id;
/**
* 用户名称
*/
@TableField(value = "user_name")
@ApiModelProperty(value = "用户名称")
private String userName;
/**
* 密码
*/
@TableField(value = "pass_word")
@ApiModelProperty(value = "密码")
private String passWord;
/**
* 加密盐值
*/
@TableField(value = "salt")
@ApiModelProperty(value = "加密盐值")
private String salt;
/**
* 1逻辑已删除值,0逻辑未删除值
*/
@TableField(value = "deleted")
@ApiModelProperty(value = "1逻辑已删除值,0逻辑未删除值")
private Integer deleted;
/**
* 创建时间
*/
@TableField(value = "create_time")
@ApiModelProperty(value = "创建时间")
private Date createTime;
/**
* 更新时间
*/
@TableField(value = "update_time")
@ApiModelProperty(value = "更新时间")
private Date updateTime;
private static final long serialVersionUID = 1L;
}
新建SysUserMapper 接口
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.hetaozi.login.entity.SysUser;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
* @email: [email protected]
* @date: 2021/11/11 10:43
* 功能:
* 描述:
* @author: 吴帆
**/
@Mapper
public interface SysUserMapper extends BaseMapper<SysUser> {
int updateBatch(List<SysUser> list);
int updateBatchSelective(List<SysUser> list);
int batchInsert(@Param("list") List<SysUser> list);
int insertOrUpdate(SysUser record);
int insertOrUpdateSelective(SysUser record);
}
新建SysUserMapper.xml
DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hetaozi.login.mapper.SysUserMapper">
<resultMap id="BaseResultMap" type="com.hetaozi.login.entity.SysUser">
<id column="id" jdbcType="BIGINT" property="id" />
<result column="user_name" jdbcType="VARCHAR" property="userName" />
<result column="pass_word" jdbcType="VARCHAR" property="passWord" />
<result column="salt" jdbcType="VARCHAR" property="salt" />
<result column="deleted" jdbcType="INTEGER" property="deleted" />
<result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
<result column="update_time" jdbcType="TIMESTAMP" property="updateTime" />
resultMap>
<sql id="Base_Column_List">
id, user_name, pass_word, salt, deleted, create_time, update_time
sql>
<update id="updateBatch" parameterType="java.util.List">
update sys_user
<trim prefix="set" suffixOverrides=",">
<trim prefix="user_name = case" suffix="end,">
<foreach collection="list" index="index" item="item">
when id = #{item.id,jdbcType=BIGINT} then #{item.userName,jdbcType=VARCHAR}
foreach>
trim>
<trim prefix="pass_word = case" suffix="end,">
<foreach collection="list" index="index" item="item">
when id = #{item.id,jdbcType=BIGINT} then #{item.passWord,jdbcType=VARCHAR}
foreach>
trim>
<trim prefix="salt = case" suffix="end,">
<foreach collection="list" index="index" item="item">
when id = #{item.id,jdbcType=BIGINT} then #{item.salt,jdbcType=VARCHAR}
foreach>
trim>
<trim prefix="deleted = case" suffix="end,">
<foreach collection="list" index="index" item="item">
when id = #{item.id,jdbcType=BIGINT} then #{item.deleted,jdbcType=INTEGER}
foreach>
trim>
<trim prefix="create_time = case" suffix="end,">
<foreach collection="list" index="index" item="item">
when id = #{item.id,jdbcType=BIGINT} then #{item.createTime,jdbcType=TIMESTAMP}
foreach>
trim>
<trim prefix="update_time = case" suffix="end,">
<foreach collection="list" index="index" item="item">
when id = #{item.id,jdbcType=BIGINT} then #{item.updateTime,jdbcType=TIMESTAMP}
foreach>
trim>
trim>
where id in
<foreach close=")" collection="list" item="item" open="(" separator=", ">
#{item.id,jdbcType=BIGINT}
foreach>
update>
<insert id="batchInsert" keyColumn="id" keyProperty="id" parameterType="map" useGeneratedKeys="true">
insert into sys_user
(user_name, pass_word, salt, deleted, create_time, update_time)
values
<foreach collection="list" item="item" separator=",">
(#{item.userName,jdbcType=VARCHAR}, #{item.passWord,jdbcType=VARCHAR}, #{item.salt,jdbcType=VARCHAR},
#{item.deleted,jdbcType=INTEGER}, #{item.createTime,jdbcType=TIMESTAMP}, #{item.updateTime,jdbcType=TIMESTAMP}
)
foreach>
insert>
<insert id="insertOrUpdate" keyColumn="id" keyProperty="id" parameterType="com.hetaozi.login.entity.SysUser" useGeneratedKeys="true">
insert into sys_user
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id != null">
id,
if>
user_name,
pass_word,
salt,
deleted,
create_time,
update_time,
trim>
values
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id != null">
#{id,jdbcType=BIGINT},
if>
#{userName,jdbcType=VARCHAR},
#{passWord,jdbcType=VARCHAR},
#{salt,jdbcType=VARCHAR},
#{deleted,jdbcType=INTEGER},
#{createTime,jdbcType=TIMESTAMP},
#{updateTime,jdbcType=TIMESTAMP},
trim>
on duplicate key update
<trim suffixOverrides=",">
<if test="id != null">
id = #{id,jdbcType=BIGINT},
if>
user_name = #{userName,jdbcType=VARCHAR},
pass_word = #{passWord,jdbcType=VARCHAR},
salt = #{salt,jdbcType=VARCHAR},
deleted = #{deleted,jdbcType=INTEGER},
create_time = #{createTime,jdbcType=TIMESTAMP},
update_time = #{updateTime,jdbcType=TIMESTAMP},
trim>
insert>
<insert id="insertOrUpdateSelective" keyColumn="id" keyProperty="id" parameterType="com.hetaozi.login.entity.SysUser" useGeneratedKeys="true">
insert into sys_user
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id != null">
id,
if>
<if test="userName != null">
user_name,
if>
<if test="passWord != null">
pass_word,
if>
<if test="salt != null">
salt,
if>
<if test="deleted != null">
deleted,
if>
<if test="createTime != null">
create_time,
if>
<if test="updateTime != null">
update_time,
if>
trim>
values
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id != null">
#{id,jdbcType=BIGINT},
if>
<if test="userName != null">
#{userName,jdbcType=VARCHAR},
if>
<if test="passWord != null">
#{passWord,jdbcType=VARCHAR},
if>
<if test="salt != null">
#{salt,jdbcType=VARCHAR},
if>
<if test="deleted != null">
#{deleted,jdbcType=INTEGER},
if>
<if test="createTime != null">
#{createTime,jdbcType=TIMESTAMP},
if>
<if test="updateTime != null">
#{updateTime,jdbcType=TIMESTAMP},
if>
trim>
on duplicate key update
<trim suffixOverrides=",">
<if test="id != null">
id = #{id,jdbcType=BIGINT},
if>
<if test="userName != null">
user_name = #{userName,jdbcType=VARCHAR},
if>
<if test="passWord != null">
pass_word = #{passWord,jdbcType=VARCHAR},
if>
<if test="salt != null">
salt = #{salt,jdbcType=VARCHAR},
if>
<if test="deleted != null">
deleted = #{deleted,jdbcType=INTEGER},
if>
<if test="createTime != null">
create_time = #{createTime,jdbcType=TIMESTAMP},
if>
<if test="updateTime != null">
update_time = #{updateTime,jdbcType=TIMESTAMP},
if>
trim>
insert>
mapper>
新建SysUserService
import java.util.List;
import com.hetaozi.login.entity.SysUser;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* @email: [email protected]
* @date: 2021/11/11 10:43
* 功能:
* 描述:
* @author: 吴帆
**/
public interface SysUserService extends IService<SysUser>{
int updateBatch(List<SysUser> list);
int updateBatchSelective(List<SysUser> list);
int batchInsert(List<SysUser> list);
int insertOrUpdate(SysUser record);
int insertOrUpdateSelective(SysUser record);
}
新建SysUserServiceImpl 继承ServiceImpl
import org.springframework.stereotype.Service;
import java.util.List;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hetaozi.login.mapper.SysUserMapper;
import com.hetaozi.login.entity.SysUser;
import com.hetaozi.login.service.SysUserService;
/**
* @email: [email protected]
* @date: 2021/11/11 10:43
* 功能:
* 描述:
* @author: 吴帆
**/
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService{
@Override
public int updateBatch(List<SysUser> list) {
return baseMapper.updateBatch(list);
}
@Override
public int updateBatchSelective(List<SysUser> list) {
return baseMapper.updateBatchSelective(list);
}
@Override
public int batchInsert(List<SysUser> list) {
return baseMapper.batchInsert(list);
}
@Override
public int insertOrUpdate(SysUser record) {
return baseMapper.insertOrUpdate(record);
}
@Override
public int insertOrUpdateSelective(SysUser record) {
return baseMapper.insertOrUpdateSelective(record);
}
}
新建测试类测试整合Mybatis-Plus是否成功,检测执行通过及说明整合成功。
package com.hetaozi.login;
import com.hetaozi.login.entity.SysUser;
import com.hetaozi.login.service.SysUserService;
import org.junit.Assert;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.Date;
import java.util.List;
@RunWith(SpringRunner.class)
@SpringBootTest
class SysUserTest {
@Autowired
private SysUserService sysUserService;
@Test
void saveUserTest() {
SysUser user = SysUser.builder()
.userName("admin")
.passWord("123456")
.salt("45678")
.createTime(new Date())
.updateTime(new Date())
.build();
int update = sysUserService.insertOrUpdate(user);
Assert.assertEquals(1,update);
}
@Test
void sysUserListTest() {
List<SysUser> list = sysUserService.list();
Assert.assertNotNull(list);
}
}
mybatis-plus学习请参照官网https://mp.baomidou.com/,国内网站哟。以上内容提供参考。
引入依赖
<dependency>
<groupId>org.apache.shirogroupId>
<artifactId>shiro-springartifactId>
<version>1.4.1version>
dependency>
此次整合基于RBAC权限管理思想整合,RBAC(Role-Based Access Control),也就是所谓的**“基于角色的访问控制权限”**。
sys_user用户表、sys_role角色表、sys_permission权限表,及其sys_user_role用户与角色关系表,sys_role_permission角色与权限关系表即可实现简单的基于RBAC登陆授权管理
CREATE DATABASE IF NOT EXISTS `rbac` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;
USE `rbac`;
DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user` (
`id` bigint(15) NOT NULL AUTO_INCREMENT COMMENT '主键',
`user_name` varchar(50) NOT NULL DEFAULT '' COMMENT '用户名称',
`pass_word` varchar(50) NOT NULL DEFAULT '' COMMENT '密码',
`salt` varchar(50) NOT NULL DEFAULT '' COMMENT '加密盐值',
`deleted` int(5) NOT NULL DEFAULT '0' COMMENT '1逻辑已删除值,0逻辑未删除值',
`create_time` datetime NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '创建时间',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
insert into `sys_user`(`id`,`user_name`,`pass_word`,`salt`,`deleted`,`create_time`,`update_time`) values
(1,'admin','a5ccf40e54bd4b7bedf9a187a127cccc','6hrOEXY35OnYWEC8juIB7A==',0,'2021-11-11 07:10:02','2021-11-11 07:19:48'),
(2,'zhangsan','bae2b0281aefbf09e420088a65054146','18pJfdQaANi4Sg7LRILbEQ==',0,'2021-11-11 08:28:46','2021-11-11 08:29:30');
DROP TABLE IF EXISTS `sys_role`;
CREATE TABLE `sys_role` (
`id` bigint(15) NOT NULL AUTO_INCREMENT COMMENT '主键',
`role_name` varchar(50) NOT NULL DEFAULT '' COMMENT '角色名称',
`sort` int(11) NOT NULL DEFAULT '-1' COMMENT 's排序',
`create_time` datetime NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '创建时间',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'updateTime',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COMMENT='角色';
insert into `sys_role`(`id`,`role_name`,`sort`,`create_time`,`update_time`) values
(1,'超级用户',1,'1000-01-01 00:00:00','2021-11-11 08:29:20'),
(2,'普通用户',2,'1000-01-01 00:00:00','2021-11-11 08:29:16');
DROP TABLE IF EXISTS `sys_permission`;
CREATE TABLE `sys_permission` (
`id` bigint(15) NOT NULL AUTO_INCREMENT COMMENT '主键',
`permission_name` varchar(50) NOT NULL DEFAULT '' COMMENT '权限',
`sort` int(11) NOT NULL DEFAULT '-1' COMMENT '排序',
`create_time` datetime NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '创建时间',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'updateTime',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COMMENT='权限';
insert into `sys_permission`(`id`,`permission_name`,`sort`,`create_time`,`update_time`) values
(1,'user:add',1,'1000-01-01 00:00:00','2021-11-11 08:29:51'),
(2,'user:update',2,'1000-01-01 00:00:00','2021-11-11 08:29:53'),
(3,'user:list',3,'1000-01-01 00:00:00','2021-11-11 08:29:54');
DROP TABLE IF EXISTS `sys_user_role`;
CREATE TABLE `sys_user_role` (
`id` bigint(15) NOT NULL AUTO_INCREMENT COMMENT '主键',
`user_id` bigint(15) NOT NULL DEFAULT '-1' COMMENT '用户id',
`role_id` bigint(15) NOT NULL DEFAULT '-1' COMMENT '角色id',
`create_time` datetime NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '创建时间',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'updateTime',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COMMENT='用户角色关联表';
insert into `sys_user_role`(`id`,`user_id`,`role_id`,`create_time`,`update_time`) values
(1,1,1,'1000-01-01 00:00:00','2021-11-11 08:14:30'),
(2,2,2,'1000-01-01 00:00:00','2021-11-11 08:29:42');
DROP TABLE IF EXISTS `sys_role_permission`;
CREATE TABLE `sys_role_permission` (
`id` bigint(15) NOT NULL AUTO_INCREMENT COMMENT '主键',
`role_id` bigint(15) NOT NULL DEFAULT '-1' COMMENT '角色id',
`permission_id` bigint(15) NOT NULL DEFAULT '-1' COMMENT '权限id',
`create_time` datetime NOT NULL DEFAULT '1000-01-01 00:00:00' COMMENT '创建时间',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'updateTime',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COMMENT='角色权限关联表';
insert into `sys_role_permission`(`id`,`role_id`,`permission_id`,`create_time`,`update_time`) values
(1,1,1,'1000-01-01 00:00:00','2021-11-11 08:15:21'),
(2,1,2,'1000-01-01 00:00:00','2021-11-11 08:15:25'),
(3,1,3,'1000-01-01 00:00:00','2021-11-11 08:15:32'),
(4,2,3,'1000-01-01 00:00:00','2021-11-11 08:30:08');
执行上面sql语句,并新建对应的entity、mapper、service如下相关数据。
import com.hetaozi.login.entity.SysUser;
import com.hetaozi.login.service.SysUserService;
import lombok.extern.slf4j.Slf4j;
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.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.Set;
/**
* @email: [email protected]
* @date: 2021/11/11 14:20
* 功能:
* 描述:
* @author: 吴帆
**/
@Slf4j
public class UserRealm extends AuthorizingRealm {
@Autowired
private SysUserService sysUserService;
/**
* 授权认证
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
log.info("授权认证...");
SysUser user = (SysUser) SecurityUtils.getSubject().getPrincipal();
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
// 角色
Set<String> roles = user.getRoles();
//权限
Set<String> permissions =user.getPermissions();
authorizationInfo.setRoles(roles);
authorizationInfo.setStringPermissions(permissions);
return authorizationInfo;
}
/**
* 登陆认证
* @param authenticationToken
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
log.info("登陆认证...");
String username = (String) authenticationToken.getPrincipal();
//更具用户名称查询用户信息,在这这查询时可以塞入用户拥有的角色集合,权限集合,菜单等
SysUser user = sysUserService.getUserByUserName(username);
if (user == null) {
// 账号不存在
throw new UnknownAccountException();
}
String salt = user.getSalt();
return new SimpleAuthenticationInfo(user,
user.getPassWord(),
ByteSource.Util.bytes(salt),
getName());
}
}
import java.util.LinkedHashMap;
import java.util.Map;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.SecurityManager;
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.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 org.springframework.context.annotation.DependsOn;
/**
* @author 260497
*/
@Configuration
public class ShiroConfig {
@Bean
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
//拦截器.
Map<String,String> filterMap = new LinkedHashMap<>();
filterMap.put("/system/login", "anon");
//放开swagger相关请求,否则swagger不能访问
filterMap.put("/swagger-ui.html", "anon");
filterMap.put("/swagger-resources", "anon");
filterMap.put("/swagger-resources/configuration/security", "anon");
filterMap.put("/swagger-resources/configuration/ui", "anon");
filterMap.put("/v2/api-docs", "anon");
filterMap.put("/webjars/springfox-swagger-ui/**", "anon");
filterMap.put("/**", "authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
return shiroFilterFactoryBean;
}
//此处的加密规则必须和存入数据库的密码加密规则一至
@Bean
public HashedCredentialsMatcher hashedCredentialsMatcher(){
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
//设置加密算法
hashedCredentialsMatcher.setHashAlgorithmName("md5");
//设置加密的次数
hashedCredentialsMatcher.setHashIterations(5);
return hashedCredentialsMatcher;
}
@Bean
public UserRealm userRealm(){
UserRealm userRealm = new UserRealm();
//存入登陆验证时使用的加密算法
userRealm.setCredentialsMatcher(hashedCredentialsMatcher());
return userRealm;
}
@Bean
public SecurityManager securityManager(){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(userRealm());
return securityManager;
}
/**
* 开启shiro aop注解支持.
* 使用代理方式;所以需要开启代码支持;
* @param securityManager
* @return
*/
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager") SecurityManager securityManager){
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
@Bean("lifecycleBeanPostProcessor")
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
@Bean
@DependsOn({"lifecycleBeanPostProcessor"})
public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
advisorAutoProxyCreator.setProxyTargetClass(true);
return advisorAutoProxyCreator;
}
}
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.UnauthorizedException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* @author 260497
*/
@Slf4j
@ControllerAdvice
public class MyLoginException {
@ResponseBody
@ExceptionHandler(UnauthorizedException.class)
public String handleShiroException(Exception ex) {
return "没有权限";
}
@ResponseBody
@ExceptionHandler(AuthorizationException.class)
public String AuthorizationException(Exception ex) {
log.error("登陆认证失败,失败信息:",ex);
return "认证失败";
}
}
/**
* @email: [email protected]
* @date: 2021/11/11 14:57
* 功能:
* 描述:
* @author: 吴帆
**/
@RestController
@Api(tags = "系统登陆相关接口")
@RequestMapping("/system")
public class LoginController {
@ApiOperation(value = "登陆")
@PostMapping("login")
public String login(String userName, String passWord){
if ("".equals(userName.trim()) || "".equals(passWord.trim())) {
return "账号或密码不能为空";
}
try {
UsernamePasswordToken token = new UsernamePasswordToken(userName, passWord);
Subject subject = SecurityUtils.getSubject();
subject.login(token);
// 处理菜单
return "登录成功";
} catch (IncorrectCredentialsException ice) {
return "密码错误";
} catch (UnknownAccountException uae) {
return "账号不存在";
} catch (LockedAccountException e) {
return "账号被锁定";
} catch (ExcessiveAttemptsException eae) {
return "操作频繁,请稍后再试";
}
}
@ApiOperation(value = "登出")
@GetMapping("loginOut")
public String loginOut(){
Subject subject = SecurityUtils.getSubject();
subject.logout();
return "登出";
}
}
测试登陆认证
使用postman或直接访问swagger测试登陆
系统目前数据库初始化了用户admin(密码123456)拥有角色超级用户,超级管理员拥有权限user:add、user:list、user:update
初始化了用户zhangsan(密码123456)拥有角色普通用户,普通用户拥有权限user:list。
登陆成功,说明登陆授权配置正确。
测试权限授权
新建UserController类测试授权
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @email: [email protected]
* @date: 2021/11/11 15:21
* 功能:
* 描述:
* @author: 吴帆
**/
@Api(tags = "用户接口")
@RestController
@RequestMapping("/user")
public class UserController {
@ApiOperation(value = "新增用户")
@RequiresPermissions(value = "user:add")
@PostMapping("/add")
public String add(){
return "新增用户成功!";
}
@ApiOperation(value = "修改用户")
@RequiresPermissions(value = "user:update")
@PostMapping("/update")
public String update(){
return "修改用户";
}
@ApiOperation(value = "用户列表查询")
@RequiresPermissions(value = "user:list")
@PostMapping("/list")
public String list(){
return "用户列表查询";
}
@ApiOperation(value = "超级用户测试没有权限")
@RequiresPermissions(value = "user:unPermission")
@PostMapping("/unPermission")
public String unPermission(){
return "505";
}
}
使用admin登陆分别访问
127.0.0.1:8080/user/add
127.0.0.1:8080/user/update
127.0.0.1:8080/user/list
均能正常访问
访问127.0.0.1:8080/user/unPermission提示没有权限,说明权限配置没有问题