1,shiro基本框架
1,什么是shiro
shro是一款主流的安全框架,不依赖任何容器,可以运行在javaEE和javaSE项目中,它的主要作用是,对访问系统的用户进行身份验证,授权,会话管理,加密等操作
shiro就是用来解决安全管理的系统化框架。
2,shiro的核心组件
用户,角色,权限之间的关系。
1,UsernamePasswordToken, shiro 用来封装用户登录信息,使用用户的登录信息来创建令牌token,
2, SecurityManager , shiro 的核心部分,负责安全认证和授权。
3,suject , shiro的一个抽象概念,包含了用户信息
4,Realm , 开发者自定义的模块,根据项目的需求,验证和授权的逻辑全部写在Realm中。
5,Authenticationnfo, 用户的角色信息集合,认证时使用。
6, AuthorzationInfo, 角色的权限信息集合,授权时使用
7,DefaultWebSecurityManager , 安全管理器,开发者自定义的Realm需要注入到 DefaultWebSecurityManager 进行管理才能生效
8,ShiroFilterFactoryBean ,过滤器工厂,Shiro的基本运行机制是由开发者来制定的,Shiro去执行,具体的执行操作就是有ShiroFilterFactoryBean 创建一个个Filter对象来完成。
shiro运行原理
2,springboot整合shiro
项目目录
1,简单集成 shiro,导入依赖
<!--使用lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- 导入shiro的依赖-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.5.3</version>
</dependency>
<!-- 连接数据的依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- 使用mybatis-plus的依赖-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.0.5</version>
</dependency>
创建一个实体类Account类并且指定表的名字
package com.zzuli.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
//使用lombok自动生成 set和get方法
@Data
@TableName("testshiro")
public class Account {
private Integer id;
private String username;
private String password;
private String perms;
private String role;
}
完成数据库,连接配置后,然后,创建mapper接口并且测试是否连接数据库成功
package com.zzuli.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zzuli.entity.Account;
import org.springframework.stereotype.Repository;
//这个接口要继承 baseMapper
//这个注解加不加都行,如果不加的话,使用 AUtowire 的时候就会爆红,加了就不会爆红了
//但是爆红不影响程序的执行
@Repository
public interface AccountMapper extends BaseMapper<Account> {
}
直接创建一个测试类
package com.zzuli.mapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
@SpringBootTest //单元测试 是否 mybatis连接是否成功
class AccountMapperTest {
//依赖注入
//因为ioc时动态代理的所以会爆红
//只要在对应的mapper接口上加入 @Repository 就不会报错。
@Resource
private AccountMapper accountMapper;
@Test
void test1(){
accountMapper.selectList(null).forEach(System.out::println);
}
}
查看输出结果
创建service层和serviceImpl层创建业务逻辑方法并且实现
IAccountService接口
package com.zzuli.service;
import com.zzuli.entity.Account;
import org.springframework.stereotype.Repository;
public interface IAccountService {
//创建一个方法用来判断用户名是否存在
Account findUsername(String username);
}
AccountServiceImpl实现类
package com.zzuli.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zzuli.entity.Account;
import com.zzuli.mapper.AccountMapper;
import com.zzuli.service.IAccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.sql.Wrapper;
@Service //表示这个类为服务层
public class AccountServiceImpl implements IAccountService {
//依赖注入
@Autowired
private AccountMapper mapper;
@Override
public Account findUsername(String username) {
//创建要给模板条件对象
QueryWrapper wrapper=new QueryWrapper<Account>();
//加入条件
wrapper.eq("username",username);
//通过名字查找对象,所以时条件查找
return mapper.selectOne(wrapper);
}
}
测试逻辑是否成功
AccountServiceImplTest
package com.zzuli.service.impl;
import com.zzuli.entity.Account;
import com.zzuli.service.IAccountService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import static org.junit.jupiter.api.Assertions.*;
//加入测试注解
@SpringBootTest
class AccountServiceImplTest {
//依赖注入
@Autowired
private IAccountService iAccountService;
@Test
void findUsername() {
Account account =iAccountService.findUsername("唐僧");
System.out.println(account);
}
}
查询测试结果
2,自定义shiro过滤器
创建一个普通类AccountRealm 并且需要继承AuthorizingRealm抽象类,并且需要实现两个方法,两个方法分别用来做认证和授权
package com.zzuli.realm;
import com.zzuli.entity.Account;
import com.zzuli.service.IAccountService;
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.springframework.beans.factory.annotation.Autowired;
public class AccountRealm extends AuthorizingRealm {
// 依赖注入
@Autowired
private IAccountService service;
/*
*
* 这个方法时用来做授权的
* */
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
/*
*
* 这个方法时用来做认证的
* */
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//authenticationToken 参数已经包含请求用户的信息
//创建一个usernamePasswordToken用来封装用户的信息,向下转型
UsernamePasswordToken token= (UsernamePasswordToken) authenticationToken;
//从封装好的token中拿取请求用户的信息
Account account =service.findUsername(token.getUsername());
//判断用户请求的信息是否存在数据库中
if (account!=null){
//程序走到这一步说明,用户发送的请求体正确,然后判断用户挈带的密码是否和数据库保持一致
//这个类可以将参数和用户请求中的参数进行对比
return new SimpleAuthenticationInfo(account,account.getPassword(),getName());
}
//account不存在
return null;
}
}
创建一个配置类ShiroConfig
配置类,逻辑结构图