本篇主要讲述springboot搭建以及利用shiro实现认证授权,没有过多关于shiro框架基础信息的描述,只是注重shiro使用详细步骤介绍。
目录
一、springboot项目的搭建
a:file -> new -> project
至此一个简单的springboot项目创建完毕,最终形式如下图:
二、 shiro框架的搭建
a:引入依赖并添加配置
<!-- shiro 安全框架--> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-all</artifactId> <version>1.5.3</version> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.3</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.2.6</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-redis</artifactId> <version>1.4.7.RELEASE</version> </dependency> <!--工具类包--> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.1.0</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- 分页插件 --> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> <version>1.3.1</version> </dependency>
application.yml配置:
#port
server:
port: 1234
spring:
####### database Config #######
datasource:
url: jdbc:mysql://localhost:3306/myshiro?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useSSL=false&allowPublicKeyRetrieval=true&useLegacyDatetimeCode=false
username: root
password: zy169693
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
####### Redis Config #######
redis:
host: 127.0.0.1
port: 6379
password: root
# 连接超时时间(毫秒)
timeout: 5000ms
# 默认的数据过期时间,主要用于shiro权限管理
expire: 2592000
jedis:
pool:
# 连接池最大连接数(使用负值表示没有限制)
max-active: 8
# 连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: -1ms
# 连接池中的最大空闲连接
max-idle: 8
# 连接池中的最小空闲连接
min-idle: 0
####### redis缓存服务配置 #######
session:
store-type: redis
jpa:
open-in-view: false
####### mybatis-plus #######
mybatis-plus:
configuration:
map-underscore-to-camel-case: true
auto-mapping-behavior: full
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
mapper-locations: classpath:mapper/*.xml
b:创建数据库表
1.用户表(认证先只创建这一个):
CREATE TABLE `sys_user` (
`user_id` int NOT NULL AUTO_INCREMENT COMMENT '用户id',
`user_name` varchar(255) NOT NULL COMMENT '用户名',
`nick_name` varchar(255) DEFAULT NULL,
`passwd` varchar(255) NOT NULL COMMENT '密码',
PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
2.用户表简单CRUD操作:
package priv.ian.demo.controller;
import cn.hutool.core.util.ObjectUtil;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import priv.ian.demo.common.Response;
import priv.ian.demo.entity.User;
import priv.ian.demo.service.SysUserService;
import priv.ian.demo.vo.UserConditionVO;
import javax.annotation.Resource;
import java.util.List;
/**
* 用户管理
*
* @author ian zhao
* @since 2021-10-04 20:27:05
*/
@Slf4j
@RestController
@RequestMapping("/sysUser")
public class RestUserController {
/**
* 服务对象
*/
@Resource
private SysUserService sysUserService;
/**
* 通过主键查询单条数据
*
* @param user 参数对象
* @return 单条数据
*/
@RequestMapping(value = "get", method = RequestMethod.GET)
public Response<User> selectOne(User user) {
User result = sysUserService.selectById(user.getId());
if (result != null) {
return Response.createSuccessResponse("查询成功", result);
}
return Response.createErrorResponse("查询失败");
}
/**
* 新增一条数据
*
* @param user 实体类
* @return Response对象
*/
@RequestMapping(value = "insert", method = RequestMethod.POST)
public Response<User> insert(User user) {
if (ObjectUtil.isEmpty(user)) {
return Response.createErrorResponse("用户为空,添加失败!");
}
try {
int result = sysUserService.insert(user);
if (result > 0) {
return Response.createSuccessResponse("新增成功", user);
}
} catch (Exception e) {
log.error("failed to insert ",e);
}
return Response.createErrorResponse("新增失败");
}
/**
* 用户修改
* @param user user
* @return response
*/
@RequestMapping(value = "update", method = RequestMethod.PUT)
public Response<User> update(@RequestBody User user) {
if (ObjectUtil.isEmpty(user)) {
return Response.createErrorResponse("用户为空,修改失败!");
}
int result = sysUserService.update(user);
if (result > 0) {
return Response.createSuccessResponse("修改成功", user);
}
return Response.createErrorResponse("修改失败");
}
/**
* 删除一条数据
*
* @param ids ids
* @return Response对象
*/
@RequestMapping(value = "delete", method = RequestMethod.DELETE)
public Response<User> delete(List<Long> ids) {
int result = sysUserService.deleteById(ids);
if (result > 0) {
return Response.createSuccessResponse("删除成功", null);
}
return Response.createErrorResponse("删除失败");
}
/**
* 查询全部
*
* @return Response对象
*/
@RequestMapping(value = "selectAll", method = RequestMethod.GET)
public Response<List<User>> selectAll() {
List<User> sysUsers = sysUserService.selectAll();
if (sysUsers != null) {
return Response.createSuccessResponse("查询成功", sysUsers);
}
return Response.createErrorResponse("查询失败");
}
/**
* 分页查询
*
* @param vo vo
* @return Response对象
*/
@RequestMapping(value = "selectPage", method = RequestMethod.GET)
public Response<PageInfo<User>> selectPage(UserConditionVO vo) {
PageInfo<User> users = sysUserService.selectPage(vo);
if (users != null) {
return Response.createSuccessResponse("查询成功", users);
}
return Response.createErrorResponse("查询失败");
}
}
c:shiro核心类的配置
shiro的核心类包括三大块(securityManager、subject、realm)以及密码匹配器(matcher),接下来依次展示。
1.密码匹配器的配置(验证密码):
package priv.ian.demo.shiro.credentials;
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;
import priv.ian.demo.util.PasswdUtil;
/**
* @Description shiro-密码凭证匹配器(验证密码)
* @Author: Ian
* @Date: 2021/10/3 8:09 下午
* @Version: ${1.0}
*/
public class CredentialsMatcher extends SimpleCredentialsMatcher {
@Override
public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
UsernamePasswordToken userToken = (UsernamePasswordToken) token;
//输入框的密码
String inPasswd = String.valueOf(userToken.getPassword());
//数据库中的加密密码
String dbPasswd = (String) info.getCredentials();
try {
dbPasswd = PasswdUtil.decrypt(userToken.getUsername(),dbPasswd);
} catch (Exception e) {
e.printStackTrace();
return false;
}
//密码校验
return this.equals(inPasswd,dbPasswd);
}
}
2.认证授权的配置(与数据库交互)
package priv.ian.demo.shiro.realm;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import priv.ian.demo.entity.User;
import priv.ian.demo.service.SysUserService;
import javax.annotation.Resource;
/**
* @Description shiro - 密码输入错误的状态下重试次数的匹配管理
* @Author: Ian
* @Date: 2021/10/9 11:45 下午
* @Version: ${1.0}
*/
public class ShiroRealm extends AuthorizingRealm {
@Resource
private SysUserService userService;
/**
* 认证
*
* @param token token
* @return info
* @throws AuthenticationException e
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//获取用户的输入账号
String username = (String) token.getPrincipal();
User user = userService.selectByUserName(username);
if (user == null) {
throw new UnknownAccountException("账号不存在!");
}
//principal 参数使用userId ,方便动态刷新用户权限
return new SimpleAuthenticationInfo(
user.getId(),
user.getPassword(),
ByteSource.Util.bytes(username),
getName()
);
}
/**
* 授权
*
* @param principalCollection s
* @return info
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
}
3. securityManager配置(shiroConfig-核心配置)
版权声明:本文为Ian_1216原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。