引入Shiro依赖
<!--shiro权限框架--> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.4.0</version> </dependency>
创建pojo实体类
Account.java(账号)
package cn.com.sway.doctor.service.common.model; import lombok.Data; @Data public class Account { private String id; private String mobile; private String password; private String name; }
Role.java(角色)
package cn.com.sway.doctor.service.common.model; public class Role { private String id; private String name; }
Permission.java(权限)
package cn.com.sway.doctor.service.common.model; public class Permission { private String id; private String name; }
创建Mapper
AuthMapper.java
package cn.com.sway.doctor.service.user.mapper; import cn.com.sway.doctor.service.common.model.Account; import org.apache.ibatis.annotations.Mapper; import java.util.List; import java.util.Map; @Mapper public interface AuthMapper { Account getAccountByMobile(String mobile); List<Map<String,Object>> getAccountPower(String mobile); }
AuthMapper.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="cn.com.sway.doctor.service.user.mapper.AuthMapper"> <!--通过手机号查找用户信息--> <select id="getAccountByMobile" resultType="cn.com.sway.doctor.service.common.model.Account" parameterType="String"> SELECT * FROM account WHERE mobile=#{mobile} </select> <!--通过手机号查找用户权限信息--> <select id="getAccountPower" resultType="java.util.HashMap" parameterType="String"> SELECT account.id, account.mobile, role.name AS role, permission.id AS permission FROM account, role, permission, account_role, role_permission WHERE account.mobile=#{mobile} AND account.id=account_role.accountId AND account_role.roleId=role.id AND role_permission.roleId=role.id AND role_permission.permissionId=permission.id </select> </mapper>
创建Service
AuthService.java
package cn.com.sway.doctor.service.user.service; import cn.com.sway.doctor.service.common.model.Account; import java.util.List; import java.util.Map; public interface AuthService { Account getAccountByMobile(String mobile); List<Map<String,Object>> getAccountPower(String mobile); }
AuthServiceImpl.java
package cn.com.sway.doctor.service.user.service.impl; import cn.com.sway.doctor.service.common.model.Account; import cn.com.sway.doctor.service.user.mapper.AuthMapper; import cn.com.sway.doctor.service.user.service.AuthService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; import java.util.Map; @Service public class AuthServiceImpl implements AuthService { @Autowired AuthMapper authMapper; @Override public Account getAccountByMobile(String mobile) { return authMapper.getAccountByMobile(mobile); } @Override public List<Map<String, Object>> getAccountPower(String mobile) { return authMapper.getAccountPower(mobile); } }
创建验证方法
ShiroRealm.java
package cn.com.sway.doctor.service.user.shiro; import cn.com.sway.doctor.service.common.model.Account; import cn.com.sway.doctor.service.user.service.AuthService; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.SimpleAuthenticationInfo; 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 java.util.List; import java.util.Map; public class ShiroRealm extends AuthorizingRealm { @Autowired private AuthService loginService; /** * 获取权限 * @param principalCollection * @return */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { //获取登录用户名 String mobile = (String) principalCollection.getPrimaryPrincipal(); //添加角色和权限 SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(); List<Map<String, Object>> powerList = loginService.getAccountPower(mobile); System.out.println(powerList.toString()); for (Map<String, Object> powerMap : powerList) { //添加角色 simpleAuthorizationInfo.addRole(String.valueOf(powerMap.get("role"))); //添加权限 simpleAuthorizationInfo.addStringPermission(String.valueOf(powerMap.get("permission"))); } return simpleAuthorizationInfo; } /** * 登录认证 * @param authenticationToken * @return * @throws AuthenticationException */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { //加这一步的目的是在Post请求的时候会先进认证,然后在到请求 if (authenticationToken.getPrincipal() == null) { return null; } //获取用户唯一标识 String mobile = authenticationToken.getPrincipal().toString(); //根据用户名去数据库查询用户信息 Account account = loginService.getAccountByMobile(mobile); if (account == null) { //这里返回后会报出对应异常 return null; } else { //这里验证authenticationToken和simpleAuthenticationInfo的信息 SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(account, account.getPassword(), getName()); return simpleAuthenticationInfo; } } }
创建配置文件
ShiroConfig.java
package cn.com.sway.doctor.service.user.config; import cn.com.sway.doctor.service.user.shiro.ShiroRealm; import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class ShiroConfig { @Bean @ConditionalOnMissingBean public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() { DefaultAdvisorAutoProxyCreator defaultAAP = new DefaultAdvisorAutoProxyCreator(); defaultAAP.setProxyTargetClass(true); return defaultAAP; } //将自己的验证方式加入容器 @Bean public ShiroRealm shiroRealm() { ShiroRealm shiroRealm = new ShiroRealm(); return shiroRealm; } //权限管理,配置主要是Realm的管理认证 @Bean public DefaultWebSecurityManager securityManager() { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(shiroRealm()); return securityManager; } //shiro核心过滤器 @Bean("shiroFilter") public ShiroFilterFactoryBean shirFilter(DefaultWebSecurityManager securityManager) { ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean(); shiroFilter.setSecurityManager(securityManager); return shiroFilter; } @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) { AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); authorizationAttributeSourceAdvisor.setSecurityManager(securityManager); return authorizationAttributeSourceAdvisor; } }
创建数据
account表:
/* Navicat Premium Data Transfer Source Server : localhost Source Server Type : MySQL Source Server Version : 50623 Source Host : localhost:3306 Source Schema : sway-doctor-service-user Target Server Type : MySQL Target Server Version : 50623 File Encoding : 65001 Date: 24/04/2023 22:12:38 */ SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for account -- ---------------------------- DROP TABLE IF EXISTS `account`; CREATE TABLE `account` ( `id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, `mobile` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact; SET FOREIGN_KEY_CHECKS = 1;
role表:
/* Navicat Premium Data Transfer Source Server : localhost Source Server Type : MySQL Source Server Version : 50623 Source Host : localhost:3306 Source Schema : sway-doctor-service-user Target Server Type : MySQL Target Server Version : 50623 File Encoding : 65001 Date: 24/04/2023 22:14:30 */ SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for role -- ---------------------------- DROP TABLE IF EXISTS `role`; CREATE TABLE `role` ( `id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact; SET FOREIGN_KEY_CHECKS = 1;
permission表:
/* Navicat Premium Data Transfer Source Server : localhost Source Server Type : MySQL Source Server Version : 50623 Source Host : localhost:3306 Source Schema : sway-doctor-service-user Target Server Type : MySQL Target Server Version : 50623 File Encoding : 65001 Date: 24/04/2023 22:14:19 */ SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for permission -- ---------------------------- DROP TABLE IF EXISTS `permission`; CREATE TABLE `permission` ( `id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact; SET FOREIGN_KEY_CHECKS = 1;
account_role表:
/* Navicat Premium Data Transfer Source Server : localhost Source Server Type : MySQL Source Server Version : 50623 Source Host : localhost:3306 Source Schema : sway-doctor-service-user Target Server Type : MySQL Target Server Version : 50623 File Encoding : 65001 Date: 24/04/2023 22:14:08 */ SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for account_role -- ---------------------------- DROP TABLE IF EXISTS `account_role`; CREATE TABLE `account_role` ( `id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, `accountId` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `roleId` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact; SET FOREIGN_KEY_CHECKS = 1;
role_permission表:
/* Navicat Premium Data Transfer Source Server : localhost Source Server Type : MySQL Source Server Version : 50623 Source Host : localhost:3306 Source Schema : sway-doctor-service-user Target Server Type : MySQL Target Server Version : 50623 File Encoding : 65001 Date: 24/04/2023 22:14:36 */ SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for role_permission -- ---------------------------- DROP TABLE IF EXISTS `role_permission`; CREATE TABLE `role_permission` ( `id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, `roleId` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `permissionId` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact; SET FOREIGN_KEY_CHECKS = 1;
使用方法
package cn.com.sway.doctor.service.user.controller.api.v1; import cn.com.sway.doctor.service.common.model.Account; import cn.com.sway.doctor.service.common.query.AccountQuery; import cn.com.sway.doctor.service.user.dao.AccountDao; import org.apache.shiro.authz.annotation.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.List; @RestController @RequestMapping("/api/v1/accounts") public class AccountsApiControllerV1 { @Autowired private AccountDao accountDao; //@RequiresAuthentication //@RequiresGuest //@RequiresUser @RequiresRoles("admin") //@RequiresPermissions("account-manage") @ResponseBody @GetMapping("") public String query() { AccountQuery accountQuery = new AccountQuery(); List<Account> list = accountDao.query(accountQuery); System.out.println(accountDao.query(accountQuery).size()); return "account total: "+list.size(); } }