首页
视频
留言
壁纸
直播
下载
友链
统计
推荐
vue
在线工具
Search
1
记一个报错GC overhead limit exceeded解决方法
960 阅读
2
ElasticSearch ES 安装 Kibana安装 设置密码
691 阅读
3
解决Mybatis-Plus批量插入数据太慢,堪称神速
356 阅读
4
Teamcity + Rancher + 阿里云Code 实现Devops 自动化部署
350 阅读
5
分布式锁Redisson,完美解决高并发问题
341 阅读
JAVA开发
前端相关
Linux相关
电商开发
经验分享
电子书籍
个人随笔
行业资讯
其他
登录
/
注册
Search
标签搜索
AOP
支付
小说
docker
SpringBoot
XML
秒杀
K8S
RabbitMQ
工具类
Shiro
多线程
分布式锁
Redisson
接口防刷
Jenkins
Lewis
累计撰写
146
篇文章
累计收到
14
条评论
首页
栏目
JAVA开发
前端相关
Linux相关
电商开发
经验分享
电子书籍
个人随笔
行业资讯
其他
页面
视频
留言
壁纸
直播
下载
友链
统计
推荐
vue
在线工具
搜索到
1
篇与
的结果
2021-11-01
SpringBoot集成Shiro实现权限管理极简教程(一)
{card-describe title="前言"}Apache Shiro是一个功能强大且易于使用的Java安全框架,提供了认证,授权,加密,和会话管理。Shiro有三大核心组件:Subject : 即当前用户,在权限管理的应用程序里往往需要知道谁能够操作什么,谁拥有操作该程序的权利,shiro中则需要通过Subject来提供基础的当前用户信息,Subject 不仅仅代表某个用户,与当前应用交互的任何东西都是Subject,如网络爬虫等。所有的Subject都要绑定到SecurityManager上,与Subject的交互实际上是被转换为与SecurityManager的交互。SecurityManager : 即所有Subject的管理者,这是Shiro框架的核心组件,可以把他看做是一个Shiro框架的全局管理组件,用于调度各种Shiro框架的服务。作用类似于SpringMVC中的DispatcherServlet,用于拦截所有请求并进行处理。Realm : Realm是用户的信息认证器和用户的权限认证器,我们需要自己来实现Realm来自定义的管理我们自己系统内部的权限规则。SecurityManager要验证用户,需要从Realm中获取用户。可以把Realm看做是数据源。通过两篇文章,我们想用最简单的教程给大家实现,SpringBoot + Shiro +JWT 实现用户权限认证控制的演示。 {/card-describe}{mtitle title="一、数据库设计"/}1.1 用户表-User SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for user -- ---------------------------- DROP TABLE IF EXISTS `user`; CREATE TABLE `user` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `account` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE ) ENGINE = MyISAM AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of user -- ---------------------------- INSERT INTO `user` VALUES (1, 'root', '超级用户', 'root'); INSERT INTO `user` VALUES (2, 'user', '普通用户', 'user'); INSERT INTO `user` VALUES (3, 'vip', 'VIP用户', 'vip'); SET FOREIGN_KEY_CHECKS = 1;{dotted startColor="#ff6c6c" endColor="#1989fa"/}1.2 角色表-RoleSET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for role -- ---------------------------- DROP TABLE IF EXISTS `role`; CREATE TABLE `role` ( `id` int(11) NOT NULL AUTO_INCREMENT, `role` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `desc` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE ) ENGINE = MyISAM AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of role -- ---------------------------- INSERT INTO `role` VALUES (1, 'admin', '超级管理员'); INSERT INTO `role` VALUES (2, 'user', '普通用户'); INSERT INTO `role` VALUES (3, 'vip_user', 'VIP用户'); SET FOREIGN_KEY_CHECKS = 1;{dotted startColor="#ff6c6c" endColor="#1989fa"/}1.3 权限表-PermissionSET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for permission -- ---------------------------- DROP TABLE IF EXISTS `permission`; CREATE TABLE `permission` ( `id` int(11) NOT NULL AUTO_INCREMENT, `permission` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '权限名称', `desc` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '权限描述', PRIMARY KEY (`id`) USING BTREE ) ENGINE = MyISAM AUTO_INCREMENT = 5 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of permission -- ---------------------------- INSERT INTO `permission` VALUES (1, 'add', '增加'); INSERT INTO `permission` VALUES (2, 'update', '更新'); INSERT INTO `permission` VALUES (3, 'select', '查看'); INSERT INTO `permission` VALUES (4, 'delete', '删除'); SET FOREIGN_KEY_CHECKS = 1;{dotted startColor="#ff6c6c" endColor="#1989fa"/}1.4 用户角色表-User_RoleSET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for user_role -- ---------------------------- DROP TABLE IF EXISTS `user_role`; CREATE TABLE `user_role` ( `id` int(11) NOT NULL AUTO_INCREMENT, `user_id` int(11) NULL DEFAULT NULL, `role_id` int(11) NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE ) ENGINE = MyISAM AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Fixed; -- ---------------------------- -- Records of user_role -- ---------------------------- INSERT INTO `user_role` VALUES (1, 1, 1); INSERT INTO `user_role` VALUES (2, 2, 2); INSERT INTO `user_role` VALUES (3, 3, 3); SET FOREIGN_KEY_CHECKS = 1;{dotted startColor="#ff6c6c" endColor="#1989fa"/}1.5 角色权限表-Role_PermissionSET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for role_permission -- ---------------------------- DROP TABLE IF EXISTS `role_permission`; CREATE TABLE `role_permission` ( `id` int(11) NOT NULL AUTO_INCREMENT, `role_id` int(11) NULL DEFAULT NULL, `permission_id` int(255) NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE ) ENGINE = MyISAM AUTO_INCREMENT = 9 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Fixed; -- ---------------------------- -- Records of role_permission -- ---------------------------- INSERT INTO `role_permission` VALUES (1, 1, 1); INSERT INTO `role_permission` VALUES (2, 1, 2); INSERT INTO `role_permission` VALUES (3, 1, 3); INSERT INTO `role_permission` VALUES (4, 1, 4); INSERT INTO `role_permission` VALUES (5, 2, 3); INSERT INTO `role_permission` VALUES (6, 3, 3); INSERT INTO `role_permission` VALUES (7, 3, 2); INSERT INTO `role_permission` VALUES (8, 2, 1); SET FOREIGN_KEY_CHECKS = 1;{dotted startColor="#ff6c6c" endColor="#1989fa"/}{mtitle title="二、项目准备"/}2.1 导入Pom<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.2</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.4.0</version> </dependency>{dotted startColor="#ff6c6c" endColor="#1989fa"/}2.2 application.ymlserver: port: 8903 spring: application: name: lab-user datasource: driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/laboratory?charset=utf8 username: root password: root mybatis: type-aliases-package: cn.ntshare.laboratory.entity mapper-locations: classpath:mapper/*.xml configuration: map-underscore-to-camel-case: true{dotted startColor="#ff6c6c" endColor="#1989fa"/}2.3 实体类2.3.1 User.java@Data @ToString public class User implements Serializable { private static final long serialVersionUID = -6056125703075132981L; private Integer id; private String account; private String password; private String username; }2.3.2 Role.java@Data @ToString public class Role implements Serializable { private static final long serialVersionUID = -1767327914553823741L; private Integer id; private String role; private String desc; }{dotted startColor="#ff6c6c" endColor="#1989fa"/}2.4 Dao层2.4.1 PermissionMapper.java@Mapper @Repository public interface PermissionMapper { List<String> findByRoleId(@Param("roleIds") List<Integer> roleIds); }2.4.2 PermissionMapper.xml<mapper namespace="cn.ntshare.laboratory.dao.PermissionMapper"> <sql id="base_column_list"> id, permission, desc </sql> <select id="findByRoleId" parameterType="List" resultType="String"> select permission from permission, role_permission rp where rp.permission_id = permission.id and rp.role_id in <foreach collection="roleIds" item="id" open="(" close=")" separator=","> #{id} </foreach> </select> </mapper>2.4.3 RoleMapper.java@Mapper @Repository public interface RoleMapper { List<Role> findRoleByUserId(@Param("userId") Integer userId); }2.4.4 RoleMapper.xml<mapper namespace="cn.ntshare.laboratory.dao.RoleMapper"> <sql id="base_column_list"> id, user_id, role_id </sql> <select id="findRoleByUserId" parameterType="Integer" resultType="Role"> select role.id, role from role, user, user_role ur where role.id = ur.role_id and ur.user_id = user.id and user.id = #{userId} </select> </mapper>2.4.5 UserMapper.java@Mapper @Repository public interface UserMapper { User findByAccount(@Param("account") String account); }2.4.6 UserMapper.xml<mapper namespace="cn.ntshare.laboratory.dao.UserMapper"> <sql id="base_column_list"> id, account, password, username </sql> <select id="findByAccount" parameterType="Map" resultType="User"> select <include refid="base_column_list"/> from user where account = #{account} </select> </mapper>{dotted startColor="#ff6c6c" endColor="#1989fa"/}2.5 Service层2.5.1 PermissionServiceImpl.java@Service public class PermissionServiceImpl implements PermissionService { @Autowired private PermissionMapper permissionMapper; @Override public List<String> findByRoleId(List<Integer> roleIds) { return permissionMapper.findByRoleId(roleIds); } }2.5.2 RoleServiceImpl.java@Service public class RoleServiceImpl implements RoleService { @Autowired private RoleMapper roleMapper; @Override public List<Role> findRoleByUserId(Integer id) { return roleMapper.findRoleByUserId(id); } }2.5.3 UserServiceImpl.java@Service public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; @Override public User findByAccount(String account) { return userMapper.findByAccount(account); } }{dotted startColor="#ff6c6c" endColor="#1989fa"/}2.6 系统返回状态枚举与包装函数2.6.1 ServerResponseEnum.java@AllArgsConstructor @Getter public enum ServerResponseEnum { SUCCESS(0, "成功"), ERROR(10, "失败"), ACCOUNT_NOT_EXIST(11, "账号不存在"), DUPLICATE_ACCOUNT(12, "账号重复"), ACCOUNT_IS_DISABLED(13, "账号被禁用"), INCORRECT_CREDENTIALS(14, "账号或密码错误"), NOT_LOGIN_IN(15, "账号未登录"), UNAUTHORIZED(16, "没有权限") ; Integer code; String message; }2.6.2 ServerResponseVO.java@Getter @Setter @NoArgsConstructor public class ServerResponseVO<T> implements Serializable { private static final long serialVersionUID = -1005863670741860901L; // 响应码 private Integer code; // 描述信息 private String message; // 响应内容 private T data; private ServerResponseVO(ServerResponseEnum responseCode) { this.code = responseCode.getCode(); this.message = responseCode.getMessage(); } private ServerResponseVO(ServerResponseEnum responseCode, T data) { this.code = responseCode.getCode(); this.message = responseCode.getMessage(); this.data = data; } private ServerResponseVO(Integer code, String message) { this.code = code; this.message = message; } /** * 返回成功信息 * @param data 信息内容 * @param <T> * @return */ public static<T> ServerResponseVO success(T data) { return new ServerResponseVO<>(ServerResponseEnum.SUCCESS, data); } /** * 返回成功信息 * @return */ public static ServerResponseVO success() { return new ServerResponseVO(ServerResponseEnum.SUCCESS); } /** * 返回错误信息 * @param responseCode 响应码 * @return */ public static ServerResponseVO error(ServerResponseEnum responseCode) { return new ServerResponseVO(responseCode); } }{dotted startColor="#ff6c6c" endColor="#1989fa"/}2.7 统一异常处理当用户身份认证失败时,会抛出UnauthorizedException,我们可以通过统一异常处理来处理该异常@RestControllerAdvice public class UserExceptionHandler { @ExceptionHandler(UnauthorizedException.class) @ResponseStatus(HttpStatus.UNAUTHORIZED) public ServerResponseVO UnAuthorizedExceptionHandler(UnauthorizedException e) { return ServerResponseVO.error(ServerResponseEnum.UNAUTHORIZED); } }{dotted startColor="#ff6c6c" endColor="#1989fa"/}{mtitle title="三、集成Shiro"/}3.1 UserRealm.java/** * 负责认证用户身份和对用户进行授权 */ public class UserRealm extends AuthorizingRealm { @Autowired private UserService userService; @Autowired private RoleService roleService; @Autowired private PermissionService permissionService; // 用户授权 protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { User user = (User) principalCollection.getPrimaryPrincipal(); SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); List<Role> roleList = roleService.findRoleByUserId(user.getId()); Set<String> roleSet = new HashSet<>(); List<Integer> roleIds = new ArrayList<>(); for (Role role : roleList) { roleSet.add(role.getRole()); roleIds.add(role.getId()); } // 放入角色信息 authorizationInfo.setRoles(roleSet); // 放入权限信息 List<String> permissionList = permissionService.findByRoleId(roleIds); authorizationInfo.setStringPermissions(new HashSet<>(permissionList)); return authorizationInfo; } // 用户认证 protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authToken) throws AuthenticationException { UsernamePasswordToken token = (UsernamePasswordToken) authToken; User user = userService.findByAccount(token.getUsername()); if (user == null) { return null; } return new SimpleAuthenticationInfo(user, user.getPassword(), getName()); } }3.2 ShiroConfig.java@Configuration public class ShiroConfig { @Bean public UserRealm userRealm() { return new UserRealm(); } @Bean public DefaultWebSecurityManager securityManager() { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(userRealm()); return securityManager; } /** * 路径过滤规则 * @return */ @Bean public ShiroFilterFactoryBean shiroFilter(DefaultWebSecurityManager securityManager) { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(securityManager); shiroFilterFactoryBean.setLoginUrl("/login"); shiroFilterFactoryBean.setSuccessUrl("/"); Map<String, String> map = new LinkedHashMap<>(); // 有先后顺序 map.put("/login", "anon"); // 允许匿名访问 map.put("/**", "authc"); // 进行身份认证后才能访问 shiroFilterFactoryBean.setFilterChainDefinitionMap(map); return shiroFilterFactoryBean; } /** * 开启Shiro注解模式,可以在Controller中的方法上添加注解 * @param securityManager * @return */ @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager") DefaultSecurityManager securityManager) { AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); authorizationAttributeSourceAdvisor.setSecurityManager(securityManager); return authorizationAttributeSourceAdvisor; }3.3 LoginController.java@RestController @RequestMapping("") public class LoginController { @PostMapping("/login") public ServerResponseVO login(@RequestParam(value = "account") String account, @RequestParam(value = "password") String password) { Subject userSubject = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken(account, password); try { // 登录验证 userSubject.login(token); return ServerResponseVO.success(); } catch (UnknownAccountException e) { return ServerResponseVO.error(ServerResponseEnum.ACCOUNT_NOT_EXIST); } catch (DisabledAccountException e) { return ServerResponseVO.error(ServerResponseEnum.ACCOUNT_IS_DISABLED); } catch (IncorrectCredentialsException e) { return ServerResponseVO.error(ServerResponseEnum.INCORRECT_CREDENTIALS); } catch (Throwable e) { e.printStackTrace(); return ServerResponseVO.error(ServerResponseEnum.ERROR); } } @GetMapping("/login") public ServerResponseVO login() { return ServerResponseVO.error(ServerResponseEnum.NOT_LOGIN_IN); } @GetMapping("/auth") public String auth() { return "已成功登录"; } @GetMapping("/role") @RequiresRoles("vip") public String role() { return "测试Vip角色"; } @GetMapping("/permission") @RequiresPermissions(value = {"add", "update"}, logical = Logical.AND) public String permission() { return "测试Add和Update权限"; } } {dotted startColor="#ff6c6c" endColor="#1989fa"/}{mtitle title="四、测试效果"/}4.1 用root用户登录4.1.1 登录4.1.2 验证是否登录4.1.3 测试角色权限4.1.4 测试用户操作权限{dotted startColor="#ff6c6c" endColor="#1989fa"/}4.2 user用户和vip用户测试略
2021年11月01日
114 阅读
0 评论
0 点赞