- 注解类
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 权限校验注解,加入之后判断是否有权限访问方法
*
* @author czs
* @date 2020-4-20 19:40:10
*/
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface PurviewValid
{
/**
* 本方法权限码
*/
int purviewId();
}
- 注解类的拦截器
import com.alibaba.fastjson.JSON;
import com.uindata.common.pojo.CommonResponse;
import com.uindata.entity.sb.TSbPurview;
import com.uindata.util.Constants;
import com.uindata.util.FastJsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
/**
* 权限校验拦截器,检查请求的方法上是否有权限注解,拿到注解内的参数值对比该用户在session内的权限集合来辨别是否有权限
*/
@Slf4j
public class PurviewValidInterceptor extends HandlerInterceptorAdapter
{
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception
{
try
{
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json; charset=utf-8");
Method method = ((HandlerMethod) handler).getMethod();
if (AnnotatedElementUtils.isAnnotated(method, PurviewValid.class))
{
final HttpSession session = request.getSession();
Object userInfo = session.getAttribute(Constants.CACHE_REDIS_KEY.USER_INFO);
final String userStr = userInfo.toString();
int purviewId = method.getDeclaredAnnotation(PurviewValid.class).purviewId();
// 获得用户存储在redis中的权限
Object purviewObj = session.getAttribute(Constants.CACHE_REDIS_KEY.USER_PURVIEW);
if (null == purviewObj)
{
response.getWriter().print(FastJsonUtils.obj2JsonStr(CommonResponse.failed("获取权限列表失败!")));
final String msg = "用户 " + userStr + " 获取权限列表失败!";
log.error(msg);
return false;
}
final List<TSbPurview> province = JSON.parseArray(purviewObj.toString(), TSbPurview.class);
if (0 == province.size())
{
response.getWriter().print(FastJsonUtils.obj2JsonStr(CommonResponse.failed("权限校验失败!")));
final String msg = "用户 " + userStr + " 权限校验失败!";
log.warn(msg);
return false;
}
final List<Integer> provinceIds = Arrays.asList(province.stream()
.map(TSbPurview::getId)
.toArray(Integer[]::new));
if (!provinceIds.contains(new Integer(purviewId)))
{
response.getWriter().print(FastJsonUtils.obj2JsonStr(CommonResponse.failed("权限校验失败!")));
final String msg = "用户 " + userStr + " 权限校验失败!";
log.warn(msg);
return false;
}
}
}
catch (Exception e)
{
log.error("权限校验失败!", e);
response.getWriter().print(FastJsonUtils.obj2JsonStr(CommonResponse.failed("权限校验失败!")));
return false;
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception
{
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception
{
}
}
-
WebConfigurer应用拦截器
import com.uindata.conf.purview.PurviewValidInterceptor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* @Description: 配置web
* 必须配置在一个类下
* @auther:
* @date: 11:51 2020/4/8
* @param:
* @return:
*/
@Configuration
@EnableSwagger2
@ConditionalOnProperty(prefix = "mconfig", name = "swagger-ui-open", havingValue = "true")
public class WebConfigurer extends WebMvcConfigurationSupport
{
/**
* 权限验证bean
*
* @return
*/
@Bean
public PurviewValidInterceptor getPurviewValidInterceptor()
{
return new PurviewValidInterceptor();
}
/**
* @Description: 配置拦截器 -> 所有以xxx开头的访问都进入RedisSessionInterceptor拦截器进行登录验证,并排除/xxx/yyy接口
* 注意:
* 必须写成链式,分别设置的话会创建多个拦截器
* 必须写成getSessionInterceptor(),否则SessionInterceptor中的@Autowired会无效
* @auther: xiaoyi
* @date: 10:11 2020/4/8
* @param: [registry]
* @return: void
*/
@Override
public void addInterceptors(InterceptorRegistry registry)
{
// 权限校验注解,拦截所有
registry.addInterceptor(getPurviewValidInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/swagger-resources/**", "/webjars/**", "/v2/**", "/swagger-ui.html/**") // 排除swagger
;
super.addInterceptors(registry);
}
}
- 使用
/**
* 删除角色
*
* @param roleId
* @return
*/
@DeleteMapping("deleteRole")
@ApiOperation(value = "删除角色")
@ApiImplicitParam(name = "roleId", value = "角色id", required = true, paramType = "query", dataType = "int")
@PurviewValid(purviewId = 50203)
public CommonResponse deleteRole(Integer roleId)
{
if (Objects.isNull(roleId))
{
return CommonResponse.failed("ID不能为空!");
}
TSbRole tSbRole = tSbRoleService.getById(roleId);
if (Objects.isNull(tSbRole))
{
return CommonResponse.failed("ID不正确!");
}
tSbRoleService.removeRole(roleId);
return CommonResponse.ok("删除成功!");
}
结语:本次的权限码被存储在了数据库,数据库中包含了用户、角色、菜单、用户角色关联、角色菜单关联等构成权限的基础表,再通过管理员的web界面去给用户授予角色、给角色授予权限,最终实现了简化版的权限控制,但这里更多的提供的是注解拦截器的一个基本思路,还是建议使用Security等第三方框架来实现权限的控制