引入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();
}
}