前言
权限控制这也是我们要用shiro框架的最主要的目的之一,对于有的接口,我们并不想让所有人都可以访问,有的加密接口需要指定权限才可以访问,我之前用Spring Security做过一次权限控制,这次学习Shiro框架也来实现一下!
数据库设计
关系图
和之前的使用SpringSecurity设计的模型完全一样,其中的结构关系如果没有做过权限控制的人需要先花一分钟来理解记忆此图!
建表SQL
/*
Navicat Premium Data Transfer
Source Server : mysql
Source Server Type : MySQL
Source Server Version : 50725
Source Host : localhost:3306
Source Schema : db1
Target Server Type : MySQL
Target Server Version : 50725
File Encoding : 65001
Date: 26/10/2020 16:21:24
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for t_permission
-- ----------------------------
DROP TABLE IF EXISTS `t_permission`;
CREATE TABLE `t_permission` (
`id` int(20) NOT NULL COMMENT 'id',
`url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'url地址',
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'url描述',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of t_permission
-- ----------------------------
INSERT INTO `t_permission` VALUES (1, '/user', 'user:user');
INSERT INTO `t_permission` VALUES (2, '/user/add', 'user:add');
INSERT INTO `t_permission` VALUES (3, '/user/delete', 'user:delete');
-- ----------------------------
-- Table structure for t_role
-- ----------------------------
DROP TABLE IF EXISTS `t_role`;
CREATE TABLE `t_role` (
`id` int(20) NOT NULL COMMENT 'id',
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '角色名称',
`memo` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '角色描述',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of t_role
-- ----------------------------
INSERT INTO `t_role` VALUES (1, 'admin', '超级管理员');
INSERT INTO `t_role` VALUES (2, 'test', '测试账户');
-- ----------------------------
-- Table structure for t_role_permission
-- ----------------------------
DROP TABLE IF EXISTS `t_role_permission`;
CREATE TABLE `t_role_permission` (
`rid` int(10) NULL DEFAULT NULL COMMENT '角色id',
`pid` int(10) NULL DEFAULT NULL
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of t_role_permission
-- ----------------------------
INSERT INTO `t_role_permission` VALUES (1, 2);
INSERT INTO `t_role_permission` VALUES (1, 3);
INSERT INTO `t_role_permission` VALUES (2, 1);
INSERT INTO `t_role_permission` VALUES (1, 1);
-- ----------------------------
-- Table structure for t_user
-- ----------------------------
DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` (
`id` int(20) NOT NULL,
`username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`passwd` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`create_time` datetime(0) NULL DEFAULT NULL,
`status` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of t_user
-- ----------------------------
INSERT INTO `t_user` VALUES (1, 'admin', '1fedc5a36d03c185065dd2b323886aa5', '2020-10-25 20:52:03', '1');
INSERT INTO `t_user` VALUES (2, 'test', '7a38c13ec5e9310aed731de58bbc4214', '2020-10-25 20:57:27', '1');
-- ----------------------------
-- Table structure for t_user_role
-- ----------------------------
DROP TABLE IF EXISTS `t_user_role`;
CREATE TABLE `t_user_role` (
`user_id` int(10) NULL DEFAULT NULL COMMENT '用户id',
`rid` int(11) NULL DEFAULT NULL COMMENT '角色id'
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of t_user_role
-- ----------------------------
INSERT INTO `t_user_role` VALUES (1, 1);
INSERT INTO `t_user_role` VALUES (2, 2);
每张表都是见名知意
授权配置
我们要先从数据库把当前用户的角色和权限查出来
ShiroRealm
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
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.springframework.beans.factory.annotation.Autowired;
import com.springboot.dao.UserMapper;
import com.springboot.dao.UserPermissionMapper;
import com.springboot.dao.UserRoleMapper;
import com.springboot.pojo.Permission;
import com.springboot.pojo.Role;
import com.springboot.pojo.User;
public class ShiroRealm extends AuthorizingRealm {
@Autowired
private UserMapper userMapper;
@Autowired
private UserRoleMapper userRoleMapper;
@Autowired
private UserPermissionMapper userPermissionMapper;
/**
* 获取用户角色和权限
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {
User user = (User) SecurityUtils.getSubject().getPrincipal();
String userName = user.getUserName();
System.out.println("用户" + userName + "获取权限-----ShiroRealm.doGetAuthorizationInfo");
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
// 获取用户角色集
List<Role> roleList = userRoleMapper.findByUserName(userName);
Set<String> roleSet = new HashSet<String>();
for (Role r : roleList) {
roleSet.add(r.getName());
}
simpleAuthorizationInfo.setRoles(roleSet);
// 获取用户权限集
List<Permission> permissionList = userPermissionMapper.findByUserName(userName);
Set<String> permissionSet = new HashSet<String>();
for (Permission p : permissionList) {
permissionSet.add(p.getName());
}
simpleAuthorizationInfo.setStringPermissions(permissionSet);
return simpleAuthorizationInfo;
}
/**
* 登录认证
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String userName = (String) token.getPrincipal();
String password = new String((char[]) token.getCredentials());
System.out.println("用户" + userName + "认证-----ShiroRealm.doGetAuthenticationInfo");
User user = userMapper.findByUserName(userName);
if (user == null) {
throw new UnknownAccountException("用户名或密码错误!");
}
if (!password.equals(user.getPassword())) {
throw new IncorrectCredentialsException("用户名或密码错误!");
}
if (user.getStatus().equals("0")) {
throw new LockedAccountException("账号已被锁定,请联系管理员!");
}
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, password, getName());
return info;
}
}
权限注解
shiro提供了相应的注解用于权限控制,如果使用这些注解就需要使用aop的功能来进行判断。shiro提供了spring aop集成,用于权限注解的解析和验证
ShiroConfig配置启用:
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
-
@RequiresAuthentication :表示当前Subject已经通过login 进行了身份验证;即Subject.
isAuthenticated()返回true -
@RequiresUse:表示当前Subject已经身份验证或者通过记住我登录的
-
@RequiresGuest :表示当前Subject没有身份验证或通过记住我登录过,即是游客身份
-
@RequiresRoles(value={“admin”, “user”}, logical= Logical.AND)
-
@RequiresPermissions (value={“user:a”, “user:b”}, logical=
Logical.OR) :表示当前Subject需要权限user:a或user:b
使用案例:
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/user")
public class UserController {
@RequiresPermissions("user:user")
@RequestMapping("list")
public String userList(Model model) {
model.addAttribute("value", "获取用户信息");
return "user";
}
@RequiresPermissions("user:add")
@RequestMapping("add")
public String userAdd(Model model) {
model.addAttribute("value", "新增用户");
return "user";
}
@RequiresPermissions("user:delete")
@RequestMapping("delete")
public String userDelete(Model model) {
model.addAttribute("value", "删除用户");
return "user";
}
}
源码地址:https://github.com/wuyouzhuguli/SpringAll/tree/master/13.Spring-Boot-Shiro-Authorization
上述代码只是实现权限控制的关键代码,完整代码还需要自己去Git上去clone
如有问题可联系QQ:707409741
或者评论下方留言,但是可能回复不及时!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/16423.html