一. 自定义权限注解
package io.coderyeah.basic.annotation;
import java.lang.annotation.*;
/**
* 自定义注解
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface PreAuthorize {
String name();
String sn();
}
二. 在接口方法上使用注解
/**
* @param deptDTO 部门查询参数
* @return Result
*/
@PreAuthorize(name = "部门列表", sn = "department:list")
@LogAnnotation(module = "部门模块", operate = "分页查询部门列表")
@ApiOperation("查询部门列表")
@PostMapping("/list")
public Result list(@RequestBody(required = false) DeptDTO deptDTO) {
return departmentService.list(deptDTO);
}
三. 登录拦截器
package io.coderyeah.basic.interceptor;
import com.alibaba.fastjson.JSON;
import io.coderyeah.basic.annotation.PreAuthorize;
import io.coderyeah.basic.constant.Constants;
import io.coderyeah.org.mapper.EmployeeMapper;
import io.coderyeah.user.domain.LoginInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.List;
import java.util.concurrent.TimeUnit;
@Component
public class LoginInterceptor implements HandlerInterceptor {
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Autowired
private EmployeeMapper employeeMapper;
@Override
public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object handler) throws Exception {
// 静态资源放行
if (!(handler instanceof HandlerMethod)) {
return true;
}
//1.获取token
String token = req.getHeader("token");
//3.如果有token,通过token获取redis的登录信息
if (token != null) {
String loginInfo = stringRedisTemplate.opsForValue().get(Constants.LOGIN_TOKEN + token); // LoginInfo对象
if (loginInfo != null) {//登录成功,而且没有过期
//5.如果登录信息不为null - 放行 + 刷新过期时间[重新添加到redis]
stringRedisTemplate.opsForValue().set(Constants.LOGIN_TOKEN + token, loginInfo, 30, TimeUnit.MINUTES);
final LoginInfo info = JSON.parseObject(loginInfo, LoginInfo.class);
if (info.getType() == 1) {
// 前端用户直接放行
return true;
}
// 后端管理员 需要判断权限
final HandlerMethod handlerMethod = (HandlerMethod) handler;
// 获取访问的方法上的权限注解
final PreAuthorize p = handlerMethod.getMethodAnnotation(PreAuthorize.class);
if (null == p) {
// 此方法上没有该注解直接放行 公用资源
return true;
}
// 需要判断该登录用户是否具备此接口的操作权限
final String sn = p.sn();
// 查询该登录用户的所有权限集合
List<String> ownPermissions = employeeMapper.getPermissionSnByLoginInfoId(info.getId());
if (ownPermissions.contains(sn)) {
// 包含该权限
return true;
}
// 没有权限返回json信息给客户端
resp.setCharacterEncoding("UTF-8");
resp.setContentType("application/json;charset=utf-8");
final PrintWriter writer = resp.getWriter();
writer.print("{\"success\":false,\"message\":\"noPermission\"}");
writer.close();
return false;
}
}
resp.setContentType("application/json;charset=UTF-8");
resp.getWriter().println("{\"success\":false,\"message\":\"noLogin\"}");
return false;
}
}
四. 查询当前登录用户的所有权限涉及到多张表
<select id="getPermissionSnByLoginInfoId" resultType="java.lang.String">
select tp.sn
from t_employee te
join t_employee_role ter on te.id = ter.employee_id
join t_role tr on ter.role_id = tr.id
join t_role_permission trp on tr.id = trp.role_id
join t_permission tp on tp.id = trp.permission_id
where te.logininfo_id = #{id}
</select>
五. 前端后置拦截器处理
//======================axios的后置拦截器【处理后台登录拦截的结果】====================//
axios.interceptors.response.use(res => {
//后端响应的是没有登录的信息
if (false === res.data.success && "noLogin" === res.data.message) {
localStorage.removeItem("token");
localStorage.removeItem("loginInfo");
router.push({path: '/login'});
}
if (false === res.data.success && "noPermission" === res.data.message) {
Message.info('您没有访问权限')
}
return res;
},error => {
Promise.reject(error)
})
//======================axios的后置拦截器【处理后台登录拦截的结果】====================//