基础知识
shiro 功能架构 依赖引入自定义Realm域,完成认证及授权过程
定义登录接口,触发subject.login(token)自定义Realm域,用于完成认证及授权过程。 shiro 配置类,配置FactoryBean及web安全管理器数据库设计
用户表资源权限表用户权限表 附
基础知识 shiro 功能
Authentication:认证;
Authorization:授权;
Session Management:会话管理,shiro拥有自己的session管理机制;
Cryptography:加密解密,管理如密码等数据;
Caching:缓存支持;
Concurrency:shiro 并发验证;
Testing:提供测试支持;
Run As:身份授权访问;
Remember Me:记住我;
这部分资料比较多,不再啰嗦。
Subject:主体,即 “用户”;
SecurityManager:shiro安全管理器,管理 Subject、负责进行认证和授权、及会话、缓存的管理。
Authenticator:认证;
Authorizer:授权;
Realm:安全域,可以有 1 个或多个 Realm;;
SessionManager:绘画管理器;
Cryptography:加密解密模块。
完整项目引入包括:
自定义Realm域,完成认证及授权过程 定义登录接口,触发subject.login(token)4.0.0 org.example springboot-shiro-demo 1.0-SNAPSHOT 8 8 org.springframework.boot spring-boot-starter-parent 2.3.6.RELEASE pom import org.springframework.boot spring-boot-starter org.springframework.boot spring-boot-autoconfigure org.springframework.boot spring-boot-starter-web com.baomidou mybatis-plus-boot-starter 3.5.0 mysql mysql-connector-java 8.0.16 org.projectlombok lombok 1.18.10 org.apache.shiro shiro-spring-boot-starter 1.8.0
这一步主要完成认证数据(用户名、密码)的获取及token的创建,然后提交shiro进行认证。
@RequestMapping("/sublogin")
public String subLogin(String userName,String password) {
Subject subject = SecurityUtils.getSubject();
AuthenticationToken token = new UsernamePasswordToken(userName,password);
try {
subject.login(token);
subject = SecurityUtils.getSubject();
// 设置shiro session (非必须)
Session shiroSession = subject.getSession();
shiroSession.setAttribute("user",subject.getPrincipal());
return "OK:"+userName;
}catch (UnknownAccountException e) {
return "用户不存在";
} catch (IncorrectCredentialsException e){
return "密码不正确";
}catch (AuthenticationException e) {
return "登录失败";
}
}
自定义Realm域,用于完成认证及授权过程。
此步骤主要完成认证、授权两个过程,并对其中认证中的密码匹配器进行了重写(MD5).
认证: 主要用于构建认证对象(从数据库读取),用于提供给shiro进行认证操作。
授权: 主要用于读取(数据库)授权信息,提供给shiro,以完成授权检查。
package cn.com.demo.shiro.config;
import cn.com.demo.shiro.entity.TShiroUser;
import cn.com.demo.shiro.service.UserService;
import cn.com.demo.shiro.util.MD5;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
@Component
public class UserRealm extends AuthorizingRealm {
@Autowired
private UserService userService;
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
// 拿到当前用户
Subject subject = SecurityUtils.getSubject();
TShiroUser user = (TShiroUser) subject.getPrincipal();
// 设置权限
simpleAuthorizationInfo.setStringPermissions(userService.getUserPermission(user.getId()));
return simpleAuthorizationInfo;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
if(StringUtils.isEmpty(token.getUsername())){
// 用户名为空
return null;
}
TShiroUser user = userService.getUserByUserName(token.getUsername());
if(user == null) {
return null;
}
return new SimpleAuthenticationInfo(user,user.getPassword(),"");
}
@Override
public CredentialsMatcher getCredentialsMatcher() {
return new CredentialsMatcher() {
@Override
public boolean doCredentialsMatch(AuthenticationToken authenticationToken, AuthenticationInfo authenticationInfo) {
UsernamePasswordToken utoken = (UsernamePasswordToken) authenticationToken;
//获得用户输入的密码
String formPassword = new String(utoken.getPassword());
//获得数据库中的密码
String dbPassword = (String) authenticationInfo.getCredentials();
try {
formPassword = MD5.encrypt(formPassword);
return dbPassword.equalsIgnoreCase(formPassword);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
};
}
}
shiro 配置类,配置FactoryBean及web安全管理器
FactoryBean: 用于构建shiro环境及配置,配置各类资源权限,鉴权信息(如登录、授权失败等)、安全管理器等配置
web安全管理器: 用于向shiro提供自定义Realm域。
此过程中,完成Factory到Realm的关联。
package cn.com.demo.shiro.config;
import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import cn.com.demo.shiro.entity.TShiroResPermission;
import cn.com.demo.shiro.service.UserService;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.linkedHashMap;
import java.util.List;
import java.util.Map;
@Configuration
public class ShiroConfig {
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(@Autowired DefaultWebSecurityManager defaultWebSecurityManager, @Autowired UserService userService){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
// shiro 内置过滤器 org.apache.shiro.web.filter.mgt.DefaultFilter
Map map = new linkedHashMap<>();
// 登录相关免认证接口
map.put("/auth
@Bean
public DefaultWebSecurityManager defaultWebSecurityManager(@Autowired UserRealm userRealm){
DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
defaultWebSecurityManager.setRealm(userRealm);
return defaultWebSecurityManager;
}
}
数据库设计
用户表
CREATE TABLE `t_shiro_user` ( `id` int NOT NULL AUTO_INCREMENT, `username` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户名', `password` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '密码', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci资源权限表
可对应实际生产的角色、菜单、按钮等跟权限有关的表
CREATE TABLE `t_shiro_res_permission` ( `id` int NOT NULL AUTO_INCREMENT, `res_path` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '资源(如url)', `permission_code` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '权限代码', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci用户权限表
对应用户权限信息;RBAC 权限方案中,还需要用户角色的参与,此表只用于简单表述用户的权限。
CREATE TABLE `t_shiro_user_permission` ( `id` int NOT NULL AUTO_INCREMENT, `user_id` int NOT NULL COMMENT '用户id', `permission_code` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '权限代码', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci附
完整源代码



