权限管理的实现思路
大约 3 分钟
前置工作
先建好权限管理的五张表: admin role permission role_admin role_permission
代码实现
先创建注解,用来标识每个方法执行时所需要的权限有哪些
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface RequestPermission {
String [] value(); // 定义一个数组,包含需要的角色
}
给需要设置权限管理的方法加上此注解
/**
* 添加图书
* @param book
* @return
*/
@Operation(summary = "增加图书接口")
@PostMapping("/saveBook")
@RequestPermission({"超级管理员"})
public R<String> saveBook(@RequestBody Book book){
boolean isSave = bookService.saveBook(book);
return isSave ? R.success("添加成功") : R.error("添加失败");
}
创建权限拦截器并实现权限检查
import com.example.bookmanager.utils.RequestPermission;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@Component
@Slf4j
public class RoleBasedAccessInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("开始拦截方法...");
if (handler instanceof HandlerMethod method) {
RequestPermission annotation = method.getMethodAnnotation(RequestPermission.class);
if (annotation != null) {
log.info("获得到该方法...");
// 假设从HttpSession中获取当前登录用户的角色
Set<String> currentUserRoles = getCurrentUserRoles(request.getSession());
// 检查当前用户是否拥有注解中要求的任何角色
if (!currentUserRoles.containsAll(Arrays.asList(annotation.value()))) {
log.info("检测到用户权限不够...");
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
return false;
}
}
}
return true;
}
/**
* 从session里面拿用户角色
* @param session
* @return
*/
private Set<String> getCurrentUserRoles(HttpSession session) {
Integer adminId = (Integer) session.getAttribute("adminId");
if (adminId != null) {
List<String> rolesInSession = (List<String>) session.getAttribute("adminRoles");
if (rolesInSession != null) {
return rolesInSession.stream().collect(Collectors.toSet());
}
}
return Collections.emptySet();
}
}
别忘了在Spring Boot配置中注册这个拦截器
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Autowired
private RoleBasedAccessInterceptor roleBasedAccessInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(roleBasedAccessInterceptor).addPathPatterns("/**"); // 添加全局拦截器
registry.addInterceptor(new LoginInterceptor())
.addPathPatterns("/**") // 拦截所有
//选择排除不需要拦截的地址
.excludePathPatterns("/login","/login.html","/regist","/regist.html");
}
}
登陆的时候,把该用户所拥有的角色添加到session里
// 给session加一个userId字段,用于拦截器的处理
HttpSession session = request.getSession();
session.setAttribute("adminId", l_admin.getId());
session.setAttribute("adminRoles",roleService.getRoles(l_admin.getId()));
System.out.println("Session中创建的adminId:" + session.getAttribute("adminId"));
System.out.println("Session中创建的adminId:" + session.getAttribute("adminRoles"));
import com.example.bookmanager.mapper.ServiceMapper;
import com.example.bookmanager.service.RoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class RoleServiceImpl implements RoleService {
@Autowired
private ServiceMapper serviceMapper;
/**
* 获取角色信息
* @param id
* @return
*/
@Override
public List<String> getRoles(Integer id) {
List<String> rolesName = serviceMapper.getRolesName(id);
return rolesName;
}
}
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.List;
@Mapper
public interface ServiceMapper {
@Select("SELECT r.name FROM role r,role_admin ra WHERE ra.admin_id = #{id} AND ra.role_id = r.id")
List<String> getRolesName(Integer id);
}
测试
因为用户的角色都存在session里,所以就需要先登录,得到cookie,染回解析出cookie,填入到postman里,进行有权限限制的功能测试,若权限不够,则会返回401
点击右侧的cookie, 输入框输入localhost点Add domain,只需要改键值对
参考
基于Springboot、RBAC思想使用注解方式实现权限管理功能_springboot拦截器实现后台接口权限控制-CSDN博客