Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。
前言:
开发工具:idea、MySQL
开发技术:MyBatis、Spring Boot、Shiro
创建数据库及测试表
-- 创建数据库
CREATE DATABASE IF NOT EXISTS shoop DEFAULT CHARSET utf8 COLLATE utf8_general_ci;
-- 创建用户表
create table shiro_user(
u_id int auto_increment primary key,
password varchar(50),
user_name VARCHAR(100)
)
insert into shiro_user(password,user_name) values('admin','[email protected]'),('123456','[email protected]')
-- 角色表
create table shiro_user_role(
r_id int auto_increment primary key,
role_name varchar(50),
user_name VARCHAR(100)
)
insert into shiro_user_role(role_name,user_name) values('admin','[email protected]'),('test','[email protected]')
-- 角色权限表
create table shiro_role_permission(
p_id int auto_increment primary key,
role_name varchar(50),
perm_name VARCHAR(100)
)
insert into shiro_role_permission(role_name,perm_name) values('admin','home_manage.html'),
('admin','get.html'),('admin','delete.html'),('test','add.html')
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.springboot</groupId>
<artifactId>five</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>five</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web-services</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- spring boot mybatis依赖 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.2.0</version>
</dependency>
<!-- 添加thymeleaf支持:类似于jsp的视图模板 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- Shiro依赖 -->
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.2.3</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
application.properties
#数据源
spring.datasource.url=jdbc:mysql://localhost:3306/shoop?serverTimezone=Asia/Shanghai&useSSL=false&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
实体类(entity)
//用户表
public class ShiroUser {
private int u_id;
private String user_name;
private String password;
//省略getter和setter方法
}
//角色表
public class Role {
private int r_id;
private String role_name;
private String user_name;
//省略getter和setter方法
}
//角色权限表
public class Pejuesejuese private int p_id;
private String role_name;
private String perm_name;
//省略getter和setter方法
}
接口(mapper)
//查询用户
@Mapper
public interface ShiroUserMapper {
public ShiroUser findByName(@Param(value = "user_name") String user_name);
}
//查询用户角色
@Mapper
public interface RoleMapper {
public Role RoleName(@Param(value = "user_name") String user_name);
}
//查询角色的权限
@Mapper
public interface PermissionMapper {
public List<Permission> PermissionPerName(@Param(value = "role_name") String role_name);
}
myBatis配置文件(xml)
<!-- 查询用户 -->
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.springboot.mapper.ShiroUserMapper">
<select id="findByName" resultType="com.springboot.entity.ShiroUser">
select * from shiro_user where user_name=#{user_name}
</select>
</mapper>
<!-- 查询用户角色-->
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.springboot.mapper.RoleMapper">
<select id="RoleName" resultType="com.springboot.entity.Role">
select *from shiro_user_role where user_name=#{user_name}
</select>
</mapper>
<!-- 查询角色的权限-->
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.springboot.mapper.PermissionMapper">
<select id="PermissionPerName" resultType="com.springboot.entity.Permission">
select *from shiro_role_permission where role_name=#{role_name}
</select>
</mapper>
业务层(service)
//查询用户
public interface ShiroUserService {
public ShiroUser findByName(@Param(value = "user_name") String user_name);
}
//查询用户角色
public interface RoleService {
public Role RoleName(@Param(value = "user_name") String user_name);
}
//查询角色的权限
public interface PermissionService {
public List<Permission> PermissionPerName(@Param(value = "role_name") String role_name);
}
业务实现层(service.impl)
//查询用户
@Service
public class ShiroUserServiceImp implements ShiroUserService {
@Resource
private ShiroUserMapper shiroUserMapper;
@Override
public ShiroUser findByName(String user_name) {
//ShiroUser user = shiroUserMapper.findByName(user_name);
return shiroUserMapper.findByName(user_name);
}
}
//查询用户角色
@Service
public class RoleServiceImpl implements RoleService {
@Resource
public RoleMapper rolemapper;
@Override
public Role RoleName(String user_name) {
//Role user = rolemapper.RoleName(user_name);
return rolemapper.RoleName(user_name);
}
}
//查询角色的权限
@Service
public class PermissionServiceImpl implements PermissionService {
@Resource
public PermissionMapper permissionMapper;
@Override
public List<Permission> PermissionPerName(String role_name) {
//List<Permission> permission = permissionMapper.PermissionPerName(role_name);
return permissionMapper.PermissionPerName(role_name);
}
}
逻辑控制层(Controller)
public class UserRealm extends AuthorizingRealm {
//认证
@Resource
public ShiroUserService shiroUserService;
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
ShiroUser user = shiroUserService.findByName(token.getUsername());
//2.判断密码
return new SimpleAuthenticationInfo(user,user.getPassword(),"");
}
//授权
@Resource
public RoleService roleService;
@Resource
public PermissionService permissionService;
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//获取当前用户的ID
Subject subject = SecurityUtils.getSubject();
ShiroUser user = (ShiroUser) subject.getPrincipal();
//查询用户的角色(身份)
Role role = roleService.RoleName(user.getUser_name());
//查询用户角色权限
List<Permission> permission = null;
try {
permission = permissionService.PermissionPerName(role.getRole_name());
} catch (Exception e) {
e.printStackTrace();
}
Set<String> permissions = new HashSet<String>();
for(Permission p:permission){
permissions.add(p.getPerm_name());
}
info.setStringPermissions(permissions);
return info;
}
}
@Configuration
public class ShiroConfig {
//创建Realm
@Bean(name = "userRealm")
public UserRealm getUserRealm(){
UserRealm userRealm = new UserRealm();
return userRealm;
}
//创建DefaultWebSecurityManager(安全管理器,关联Realm)
@Bean(name = "securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//关联Realm
securityManager.setRealm(userRealm);
return securityManager;
}
//创建ShiroFilterFactoryBean(用户主体,把操作交给SecurityManager)
@Bean(name = "DefaultWebSecurityManager")
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
//设置安全管理器
shiroFilterFactoryBean.setSecurityManager(securityManager);
//添加shiro内置过滤器,可以实现相关权限拦截
Map<String,String> filterMap = new LinkedHashMap<String, String>();
filterMap.put("/tet/test","anon");
filterMap.put("/tet/login","anon");
//Tips:当授权拦截后,Shiro会自动跳转到未授权界面
filterMap.put("/tet/add", "perms[add.html]");
filterMap.put("/tet/update", "perms[get.html]");
filterMap.put("/tet/delete", "perms[delete.html]");
filterMap.put("/tet/**","authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
shiroFilterFactoryBean.setLoginUrl("/tet/toLogin");
shiroFilterFactoryBean.setSuccessUrl("/tet/hello");
shiroFilterFactoryBean.setUnauthorizedUrl("/tet/noAuth");
return shiroFilterFactoryBean;
}
//配置ShiroDialect,用于thymeleaf和shiro标签的配合使用
@Bean
public ShiroDialect getShiroDialect(){
return new ShiroDialect();
}
}
@RequestMapping("/tet")
@Controller
public class testController {
@RequestMapping("/login")
public String login(String user_name, String password){
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(user_name,password);
try {
subject.login(token);
return "test";
} catch (AuthenticationException e) {
return "a";
}
}
@RequestMapping("/test")
public String test(){
return "home";
}
@RequestMapping("/add")
public String add() {
return "add";
}
@RequestMapping("/update")
public String update(){
return "update";
}
@RequestMapping("/delete")
public String delete(){
return "delete";
}
@RequestMapping("/toLogin")
public String toLogin(){
return "login";
}
@RequestMapping("/hello")
public String hello(){
return "a";
}
@RequestMapping("/noAuth")
public String noAuth(){
return "s";
}
}
登录HTML
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/tet/login" method="post">
用户名:<input type="text" name="user_name"><br>
密码:<input type="password" name="password"><br>
<input type="submit" value="login">
</form>
</body>
</html>
首页HTML
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<shiro:hasPermission name="add.html">
用户添加:<a href="add">添加用户</a><br>
</shiro:hasPermission>
<shiro:hasPermission name="get.html">
用户修改:<a href="update">修改用户</a><br>
</shiro:hasPermission>
<shiro:hasPermission name="delete.html">
用户删除:<a href="delete">删除用户</a><br>
</shiro:hasPermission>
</body>
</html>
项目源码https://pan.baidu.com/s/1Lcn_ovMz48UoKz7p_xQsHA提取码:m55s