个人简介:Java领域新星创作者;阿里云技术博主、星级博主、专家博主;正在Java学习的路上摸爬滚打,记录学习的过程~
个人主页:.29.的博客
学习社区:进去逛一逛~
⑤【Shiro】SpringBoot整合Shiro,实现登录认证
- 目录结构
- Maven坐标导入
- 准备用于登录校验的数据
- 数据库表对应的实体类
- SpringBoot配置文件
- MyBatis-Plus操作数据库的Mapper接口
- Service层,提供一个根据name查询用户的业务方法
- 自定义Realm,实现自定义登录认证
- 控制层,使用Shiro进行登录认证
- Shiro配置类,使自定义Realm生效,设置拦截范围
- 测试登录认证功能
目录结构
目录结构
:
Maven坐标导入
pom.xml
:
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.2.1.RELEASE</version></parent><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring-boot-web-starter</artifactId><version>1.9.0</version></dependency><!--mybatis-plus--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.0.5</version></dependency><!--mysql--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.46</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency></dependencies>
准备用于登录校验的数据
创建表结构,插入数据
:
CREATE DATABASE IF NOT EXISTS `shirodb` CHARACTER SET utf8mb4;
USE `shirodb`;
CREATE TABLE `user` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '编号',
`name` VARCHAR(30) DEFAULT NULL COMMENT '用户名',
`pwd` VARCHAR(50) DEFAULT NULL COMMENT '密码',
`rid` BIGINT(20) DEFAULT NULL COMMENT '角色编号',
PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='用户表';# e8e2ea5deb7e981462ab88c2b7e3f19a 是123456789经过MD5加盐三次机密后的结构,加的盐为"salt"
insert into user values(1, '.29.', 'e8e2ea5deb7e981462ab88c2b7e3f19a', 1);
数据库表对应的实体类
User
:
/*** @author .29.* @create 2024-03-17 10:53*/
//lombok组件注解,提供构造器以及Getter、Setter
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {private Integer id;private String name;private String pwd;private Integer rid;
}
SpringBoot配置文件
applicaition.yml
:
# mybatis-plus配置
mybatis-plus:configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImplmapper-locations: classpath:mapper/*.xml
spring:# 数据库连接配置datasource:type: com.zaxxer.hikari.HikariDataSourcedriver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://localhost:3306/shirodb?characterEncoding=utf-8&useSSL=falseusername: rootpassword: abc123jackson:date-format: yyyy-MM-dd HH:mm:sstime-zone: GMT+8
MyBatis-Plus操作数据库的Mapper接口
UserMapper
:
/*** @author .29.* @create 2024-03-17 10:55@Repository注解用于标识一个类作为数据访问层(DAO)的组件,类似于@Component,但可以将底层数据访问技术(如 JDBC、Hibernate 等)所抛出的异常转换为 Spring 的数据访问异常(DataAccessException),这样在上层代码中可以统一处理数据访问异常。*/
@Repository
public interface UserMapper extends BaseMapper<User> {
}
Service层,提供一个根据name查询用户的业务方法
Service接口
:
/*** @author .29.* @create 2024-03-17 10:56*/
public interface UserService {//用户登录User getUserInfoByName(String name);
}
Service实现类
:
/*** @author .29.* @create 2024-03-17 10:57*/
@Service
public class UserServiceImpl implements UserService {@Autowiredprivate UserMapper userMapper;/*** 根据name查询用户的业务方法* @param name* @return*/@Overridepublic User getUserInfoByName(String name) {QueryWrapper<User> queryWrapper = new QueryWrapper<>();queryWrapper.eq("name", name);User user = userMapper.selectOne(queryWrapper);return user;}
}
自定义Realm,实现自定义登录认证
MyRealm
:
/*** @author .29.* @create 2024-03-17 11:01*/
@Configuration
public class MyRealm extends AuthorizingRealm {//自定义Realm需要继承AuthorizingRealm@Autowiredprivate UserService userService;/*** 自定义授权方法,这里暂时不需要设置,直接返回null* @param principalCollection* @return*/@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {return null;}/*** 自定义登录认证方法* @param authenticationToken* @return* @throws AuthenticationException*/@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {//从token中获取用户身份信息String name = authenticationToken.getPrincipal().toString();//查询数据库中的用户信息User user = userService.getUserInfoByName(name);//判断并将数据封装进进行登录认证的对象,进行返回if(user != null && name.equals(user.getName())){//创建实现了校验逻辑的对象,传入校验数据,交给shiro底层进行认证SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(authenticationToken.getPrincipal(), user.getPwd(), ByteSource.Util.bytes("salt"), name);return info;}return null;}
}
控制层,使用Shiro进行登录认证
myController
:
/*** @author .29.* @create 2024-03-17 11:27*/
@Controller
@RequestMapping("/myController")
public class MyController {@GetMapping("/userLogin")@ResponseBodypublic String userLogin(String name, String pwd){//获取subject对象Subject subject = SecurityUtils.getSubject();//封装请求数据至tokenUsernamePasswordToken token = new UsernamePasswordToken(name, pwd);//调用login方法进行登录认证try{subject.login(token);System.out.println("登陆成功!");return "登陆成功";}catch (AuthenticationException e){e.printStackTrace();System.out.println("登陆失败!");return "登陆失败";}}
}
Shiro配置类,使自定义Realm生效,设置拦截范围
ShiroConfig
:
/*** @author .29.* @create 2024-03-17 11:14*/
@Configuration
public class ShiroConfig {@Autowiredprivate MyRealm myRealm;//配置SecurityManager@Beanpublic DefaultWebSecurityManager defaultWebSecurityManager(){//创建DefaultWebSecurityManager对象(安全管理器)DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();//创建加密对象,设置属性HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();hashedCredentialsMatcher.setHashAlgorithmName("MD5"); //使用什么加密算法?hashedCredentialsMatcher.setHashIterations(3); //循环加密几次?myRealm.setCredentialsMatcher(hashedCredentialsMatcher); //为自定义Realm设置加密对象defaultWebSecurityManager.setRealm(myRealm); //将自定义Realm存入安全管理器return defaultWebSecurityManager; //返回安全管理器}//配置Shiro内置过滤器拦截范围@Beanpublic DefaultShiroFilterChainDefinition defaultShiroFilterChainDefinition(){//创建拦截器定义对象DefaultShiroFilterChainDefinition filter = new DefaultShiroFilterChainDefinition();//配置不认证也能访问的资源(参数anon代表无需认证)filter.addPathDefinition("/myController/userLogin","anon");filter.addPathDefinition("/login","anon");//配置需要认证访问的资源(参数authc代表需要认证)filter.addPathDefinition("/**","authc");return filter;}
测试登录认证功能
启动项目,访问地址传递参数
: