文章目录
手把手教你用SpringBoot整合Shiro
1、shiro的前世今生
1.1、shiro是什么?
上面是Apache公司对Shiro的一个简单的介绍。简单总结,Shiro是Apache公司的一个产品,它是一款易于使用的Java安全框架(不仅可以使用在JavaEE上,也可以使用在JavaSE上哦)。它的主要功能有:登录认证、权限认证、加密、会话管理。
1.2、为什么要使用shiro?
我觉得Shiro框架主要是解决Web应用的路径访问的限制问题。举个例子,在一个简单的Web项目,怎么防止未登录或者授权的用户,通过输入路径,来非法访问系统内部的资源呢?当然可以通过自定义filter结合session来实现。但是这方面,Shiro做得明显更好。既然有摩托车,为什么还要使用自行车呢?其次,Shiro还可以对会话进行管理,结合token,还可以解决session在分布式中储存问题,也可以避免伪站请求攻击的问题。所以学习Shiro还是有必要的。
2、Shiro的运作流程
在Shiro当中,主要有以下几个模块:
Subject:当前与程序进行交互的实体(可以是用户,第三方服务,计划任务等)的特定于安全性的“视图”。
Security Manager:SecurityManager是Shiro体系结构的核心。它作为一个环境,用于协调其托管组件以确保它们能够顺利协同工作。它还管理Shiro对每个应用程序用户的视图,因此它知道如何对每个用户执行安全性操作。
Authenticator:登录认证器。
Authorizer:授权认证器。
Session Manager:创建和管理用户Session生命周期的组件容器。
Cache Manager:创建和管理Cache组件使用实例的生命周期的组件容器。
Session DAO:可以通过Cache储存Session。
Realm:Realm充当Shiro与应用程序的安全数据之间的“桥梁”或“连接器”。
Cryptography:Shiro的crypto软件中包含易于使用和理解的加密算法,可用于对密码的加密解密。
通过上面的图,我们可以清晰地看到Shiro的执行流程。首先用户通过获取Shiro中的Subject对象,使用Subject对象的login方法进行登录,在构建好的Security Manager环境中,我们通过Realm进行登录的校验和权限的分配。
上面有提到Realm是Shiro与应用程序的安全数据之间的“桥梁”或“连接器”。为什么这样说?是因为我们通过Subject对象,获取登录的账号名,再通过账号名,查询数据库,找到对应的正确密码,然后把账号和密码存放在Realm里。当Subject对象执行login方法登录时,可以进行账号密码的校验。如果正确,则分配具体的权限。如果失败,则返回相应的异常。
那配置Security Manager有什么用呢?全局就只有一个Security Manager,它作为作为Shiro运行的环境,可以绑定许多模块,例如Shiro的拦截器、Realm、SessionManager等。所以一定要配置它。
3、实战–SpringBoot如何整合Shiro
3.1、准备数据库
登录账号表
角色表
权限表
登陆账号、角色关系表
角色、权限关系表
3.2、引入依赖
pom文件引入依赖
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0</version>
</dependency>
3.3、编写底层的CRUD方法
LoginMapper.java
@Repository
public interface LoginMapper {
//根据账号查找用户
@Select("select * from login where username = #{name}")
public Login findone(String name);
//根据编号查找用户
@Select("select * from login where id = #{id}")
public Login findbyid(int id);
//根据账号和密码查找用户
@Select("select * from login where username = #{name} and password = #{pwd}")
public Login findbynameandpwd(String name,String pwd);
}
PermissionMapper.java
@Repository
public interface PermissionMapper {
//使用左外连接,连接角色表和权限表
//根据角色的编号,查找角色对应的权限集合
@Select("SELECT permission.id,permission.`name`,permission.url " +
"FROM role_permission LEFT JOIN permission ON role_permission.p_id=permission.id " +
"WHERE role_permission.r_id= #{roleid}")
public List<Permission> findPermissionListByRoleId(int roleid);
}
RoleMapper.java
@Repository
public interface RoleMapper {
//多表查询,使用左外连接,连接登录表、角色表、权限表
//根据用户名称查找用户对应的角色以及角色对应的权限
@Select("SELECT role.id,role.name,role.description " +
"FROM user_role LEFT JOIN role on user_role.role_id=role.id WHERE user_role.user_id= #{userid}")
@Results(
value = {
@Result(id = true,property = "id",column = "id"),
@Result(property = "name",column = "name"),
@Result(property = "description",column = "description"),
@Result(property = "permissionList",column = "id",
many = @Many(select = "com.example.denglu.dao.PermissionMapper.findPermissionListByRoleId",fetchType = FetchType.DEFAULT))
}
)
public List<Role> findRoleListByid(int userid);
}
3.4、设置CustomRealm
public class CustomRealm extends AuthorizingRealm {