创建项目
创建自定注解
- 创建annotation.Permission 注解接口
package com.qcby.annotation; @Target(ElementType.METHOD) //注解用于字段上 @Retention(RetentionPolicy.RUNTIME) // 保留到运行时,可通过注解获取 public @interface Permission { String value() default ""; }
权限分配(方法二)
- 数据库创建permission,ref_user_permission 表
CREATE TABLE `permission` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `url` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; CREATE TABLE `ref_user_permission` ( `user_id` bigint(20) NOT NULL, `permission_id` bigint(20) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
- 编辑MenuMapper接口,添加getPermissionListById方法
public interface MenuMapper { public Set<String> getPermissionListById(@Param("id") Long id); }
- 编辑MenuMapper.xml,添加getPermissionListById方法
<?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="com.qcby.mapper.MenuMapper"> <select id="getPermissionListById" resultType="java.lang.String"> select url from permission left join ref_user_permission on permission.id=ref_user_permission.permission_id where ref_user_permission.user_id=#{id} </select> </mapper>
- 编辑MenuService接口,添加getPermissionListById方法
public interface MenuService { public Set<String> getPermissionListById(Long id); }
- 编辑MenuServiceImpl类,实现getPermissionListById方法(根据用户id获取权限)
@Service public class MenuServiceImpl implements MenuService { @Resource private MenuMapper menuMapper; @Override public Set<String> getPermissionListById(Long id) { return this.menuMapper.getPermissionListById(id); } }
- 给想要分配权限的方法加上注解
@Permission("student")//自定义注解 @GetMapping("getUsers") public List<User> getUsers(){ return this.service.list(); }
- 编辑UserController中的登录方法
package com.qcby.controller; @RestController @RequestMapping("login") public class UserController { @Autowired private UserServiceImpl service; @Autowired private HttpSession session; @Autowired private MenuServiceImpl menuService; @RequestMapping(value = "login",method = RequestMethod.GET) public Map<String,Object> login(User user){ Map<String,Object> map = new HashMap<>(); map.put("code",0); if(StringUtils.isEmpty(user.getUsername()) || StringUtils.isEmpty(user.getPassword()) ){ map.put("msg","用户或者密码为空!"); return map; } QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.eq("username",user.getUsername()) .eq("password",user.getPassword()); User userDb = service.getOne(queryWrapper); if(userDb != null){ map.put("code",1); map.put("data",userDb); /*session.setAttribute("username",userDb.getUsername());*/ String token= TokenUtil.generateToken(userDb); map.put("qcby-token",token); // *重点* //调用getPermissionListById方法获取登陆的用户的所有权限,放到User //实体类的url属性里面 Set<String> url=menuService.getPermissionListById(userDb.getId()); userDb.setUrl(url); }else{ map.put("msg","用户名或密码错误!"); } return map; } @Permission("student")//自定义注解 @GetMapping("findAll") public List<User> findAll(){ return this.service.findAll(); } }
- 编辑LoginInterceptor拦截器,实现通过注解分配角色
package com.qcby.interceptor; public class LoginInterceptor implements HandlerInterceptor { private Logger log = LoggerFactory.getLogger(getClass()); @Autowired private HttpSession httpSession; //Controller逻辑执行之前 @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("preHandle...."); String uri = request.getRequestURI(); System.out.println("uri:"+ uri); /* HandlerMethod=>Controller中标注@RequestMapping的方法 * 需要配置静态资源不拦截时,添加这块逻辑 => 前后端分离项目 */ if (!(handler instanceof HandlerMethod)) { return true; } String token=request.getHeader("qcby-token"); if (!TokenUtil.verify(token)) { // 未登录跳转到登录界面 response.sendRedirect("/login/login"); return false; }else { //登录成功 HandlerMethod handlerMethod=(HandlerMethod)handler; //通过反射获取用户访问的接口的自定义注解 Permission permission=handlerMethod.getMethodAnnotation(Permission.class); //如果注解不为null if(permission!=null){ //获取用户信息 User user=TokenUtil.getUser(token); //获取用户url属性 Set<String> url=user.getUrl(); //自定义注解的值存在于url集合里面 if(url.contains(permission.value())){ //允许访问 return true; }else { //注解的值不在集合里面,不允许访问 //throw new Exception("权限不足"); return false; } }else { //如果注解为null,不允许访问 return false; } } } //Controller逻辑执行完毕但是视图解析器还未进行解析之前 @Override public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception { System.out.println("postHandle...."); } //Controller逻辑和视图解析器执行完毕 @Override public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception { System.out.println("afterCompletion...."); } }
源码
仓库中demo0327是源码 稍加修改即可运行