首先说一下,是很简单的权限控制,user表和role表,还有一个role和user关联表。
流程:用户访问接口,接口加上自己的切面注解,注解传入所需的权限,进入切面后进行相应判断。
注意:我这里的获取用户信息用到了token,token里面存入了用户id,需要token工具类的key留言发给你。
下面开始代码
为什么要自己发一个:网上有很多,但是都不能直接使用,需要自己解读,我写的这个不说多好,但是逻辑清晰,代码简单,扩展性比较强,而且除了获取用户那块,其他代码都可以直接复制到项目中 使用。
定义注解类
package com.section;
import java.lang.annotation.*;
//定义注解用在方法上
@Target({ElementType.METHOD})
//定义保留策略,运行时使用
@Retention(RetentionPolicy.RUNTIME)
public @interface SectionNote {
String value() default "";
}
切面类逻辑
package com.section;
import com.login.domain.SysUserRole;
import com.login.mapper.SysMenuMapper;
import com.login.mapper.SysRoleMenuMapper;
import com.login.mapper.SysUserRoleMapper;
import com.token.JwtUtil;
import com.util.AjaxResponse;
import com.util.ServletUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.List;
//交给spring管理
@Component
//标识切面
@Aspect
public class Section {
@Autowired
private SysUserRoleMapper sysUserRoleMapper;
@Autowired
private SysRoleMenuMapper sysRoleMenuMapper;
@Autowired
private SysMenuMapper sysMenuMapper;
// 以自定义 @SectionNote 注解为切点
@Pointcut("@annotation(com.section.SectionNote)")
public void sectionNote(){}
@Around("sectionNote()")
public AjaxResponse doAround(ProceedingJoinPoint joinPoint) {
//获取切面参数
String sectionNoteInfo = getSectionNoteInfo(joinPoint);
//获取用户权限
int userRole = getUserRole();
//判断是否有权限 1有 -1 没有
int i = accessControl(sectionNoteInfo,userRole );
if(i==1){
//有权限,执行方法
try {
return AjaxResponse.success(joinPoint.proceed());
} catch (Throwable throwable) {
throwable.printStackTrace();
return AjaxResponse.error("访问的内容出错");
}
}else{
//没有权限,返回错误码
return AjaxResponse.error("没有权限操作此内容");
}
}
/**
* 获取注解信息
*
* @param joinPoint
* @return
* @throws Exception
*/
public String getSectionNoteInfo(JoinPoint joinPoint) {
// 获取切入点的目标类
Class<?> aClass = joinPoint.getTarget().getClass();
String targetName = joinPoint.getTarget().getClass().getName();
Class<?> targetClass = null;
try {
targetClass = Class.forName(targetName);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
// 获取切入方法名
String methodName = joinPoint.getSignature().getName();
// 获取切入方法参数
Object[] arguments = joinPoint.getArgs();
// 获取目标类的所有方法
Method[] methods = targetClass.getMethods();
for (Method method : methods) {
// 方法名相同、包含目标注解、方法参数个数相同(避免有重载)
if (method.getName().equals(methodName) && method.isAnnotationPresent(SectionNote.class)
&& method.getParameterTypes().length == arguments.length) {
return method.getAnnotation(SectionNote.class).value();
}
}
return "";
}
/**
* 获取用户权限
* */
public int getUserRole(){
//获取request
HttpServletRequest request = ServletUtils.getRequest();
//获取token
String accessToken = request.getHeader("accessToken");
//获取用户id
String userInfo = JwtUtil.getUserInfo(accessToken,"userId");
//获取用户的角色
SysUserRole userRole = sysUserRoleMapper.getUserRoleUserId(Integer.parseInt(userInfo));
return userRole.getRoleId();
}
/**
* 判断是否有权限
* @param sectionNoteInfo 注解上的值
* @param userRole 用户的权限
* */
public int accessControl(String sectionNoteInfo,int userRole){
//判断是否符合权限
if (sectionNoteInfo.equals(String.valueOf(userRole))) {
//执行方法
return 1;
}
return -1;
}
}
用到的工具类
package com.section;
public class AssessDeniedException extends RuntimeException{
/**
*
*/
private static final long serialVersionUID = 5188167616201017971L;
public AssessDeniedException() {
super();
// TODO Auto-generated constructor stub
}
public AssessDeniedException(String message, Throwable cause,
boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
// TODO Auto-generated constructor stub
}
public AssessDeniedException(String message, Throwable cause) {
super(message, cause);
// TODO Auto-generated constructor stub
}
public AssessDeniedException(String message) {
super(message);
// TODO Auto-generated constructor stub
}
public AssessDeniedException(Throwable cause) {
super(cause);
// TODO Auto-generated constructor stub
}
}
用到的工具类2
package com.util;
import cn.hutool.core.convert.Convert;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
/**
* 客户端工具类
*/
public class ServletUtils {
/**
* 获取ServletRequestAttributes
* */
public static ServletRequestAttributes getRequestAttributes() {
RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
return (ServletRequestAttributes) attributes;
}
/**
* 获取request
*/
public static HttpServletRequest getRequest() {
return getRequestAttributes().getRequest();
}
在controller中运用
package com.demo.controller;
import com.demo.domain.SysProject;
import com.demo.service.ISysProjectService;
import com.section.SectionNote;
import com.util.AjaxResponse;
import com.util.DataUtil;
import net.sf.json.JSONObject;
import org.junit.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/project")
public class SysProjectController{
@Autowired
private ISysProjectService sysProjectService;
/**
* 查询项目列表
* @SectionNote(value = "1") 这个就是自己定义的注解,传入一个1的权限
*/
@SectionNote(value = "1")
@GetMapping("/list")
public vois alist(SysProject sysProject) {
System.out.println("有权限,进入此接口");
}
}
需要token方法的,可以留言,如果确实有需要我可以在写一个token的类
2021年4月28日补充:之前写了token工具类,把地址放到这里:
https://blog.csdn.net/qq_42236784/article/details/114022116
这样token认证和权限认证就全了;