SpringMVC拦截器+Spring自定义注解实现权限验证
设计思路
主要针对需要登录后操作的接口进行校验。接入层在对外暴露接口后,网页、APP、第三方等等途径进行访问接口。用户请求首先会被SpringMVC拦截器拦截到,在拦截器里第一步就是需要校验用户的登录身份(由于是分布式系统这里采用的是userId+accessToken方式来校验),登录校验通过之后再进行用户权限校验,此时会自动拦截@AuthValidate注解的method(核心),如果权限校验失败则抛出权限不足异常,否则校验通过之后再执行具体接口并返回结果。
1、自定义注解
package com.mao.auth;
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; /**
*
* 项目名称:---
* 模块名称:接入层
* 功能描述:权限定义
* 创建人: mao2080@sina.com
* 创建时间:2017年5月9日 下午8:41:05
* 修改人: mao2080@sina.com
* 修改时间:2017年5月9日 下午8:41:05
*/
@Target(value = ElementType.METHOD)
@Retention(value = RetentionPolicy.RUNTIME)
@Documented
public @interface AuthValidate { /**
*
* 描述:权限定义
* @author mao2080@sina.com
* @created 2017年5月8日 上午11:36:41
* @since
* @return 权限代码
*/
AuthCode value() default AuthCode.Allow; }
2、权限枚举
package com.mao.auth; /**
*
* 项目名称:---
* 模块名称:接入层
* 功能描述:权限类型枚举
* 创建人: mao2080@sina.com
* 创建时间:2017年5月8日 上午11:43:12
* 修改人: mao2080@sina.com
* 修改时间:2017年5月8日 上午11:43:12
*/
public enum AuthCode { Allow("00000", "00000", "允许访问"), /******************客户权限******************/ AU0001("100001", "AU0001", "新增用户", "新增用户"), AU0002("100002", "AU0002", "删除用户", "批量删除用户"); /**权限标识 */
private String authId; /**权限编码 */
private String authCode; /**权限名称 */
private String authName; /**权限描述 */
private String authDesc; /**
*
* 描述:构建设备类型
* @author mao2080@sina.com
* @created 2017年3月22日 上午13:50:58
* @since
* @param authId 权限标识
* @param authCode 权限编码
* @param authName 权限名称
* @return
*/
private AuthCode(String authId, String authCode, String authName) {
this.authId = authId;
this.authCode = authCode;
this.authName = authName;
} /**
*
* 描述:构建设备类型
* @author mao2080@sina.com
* @created 2017年3月22日 上午13:50:58
* @since
* @param authId 权限标识
* @param authCode 权限编码
* @param authName 权限名称
* @param authDesc 权限描述
* @return
*/
private AuthCode(String authId, String authCode, String authName, String authDesc) {
this.authId = authId;
this.authCode = authCode;
this.authName = authName;
this.authDesc = authDesc;
} public String getAuthId() {
return authId;
} public void setAuthId(String authId) {
this.authId = authId;
} public String getAuthCode() {
return authCode;
} public void setAuthCode(String authCode) {
this.authCode = authCode;
} public String getAuthDesc() {
return authDesc;
} public void setAuthDesc(String authDesc) {
this.authDesc = authDesc;
} public String getAuthName() {
return authName;
} public void setAuthName(String authName) {
this.authName = authName;
} @Override
public String toString() {
return String.format("authId:%s, authCode:%s, authName:%s, authDesc:%s", this.authId, this.authCode, this.authName, this.authDesc);
} }
3、Controller使用自定义注解
package com.mao.controller; import javax.servlet.http.HttpServletRequest; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody; import com.mao.auth.AuthCode;
import com.mao.auth.AuthValidate;
import com.mao.beans.ResObject;
import com.mao.exception.BusinessException; /**
*
* 项目名称:---
* 模块名称:接入层
* 功能描述:用户控制层
* 创建人: mao2080@sina.com
* 创建时间:2017年5月9日 下午8:15:50
* 修改人: mao2080@sina.com
* 修改时间:2017年5月9日 下午8:15:50
*/
@Controller
@RequestMapping("/userController")
public class UserController { /**日志*/
@SuppressWarnings("unused")
private static final Log loger = LogFactory.getLog(UserController.class); /**
*
* 描述:新增用户
* @author mao2080@sina.com
* @created 2017年5月9日 下午8:16:41
* @since
* @param request
* @return
* @throws BusinessException
*/
@RequestMapping("/createUser")
@ResponseBody
@AuthValidate(AuthCode.AU0001)
public ResObject createUser(HttpServletRequest request) throws BusinessException{
//业务代码
return new ResObject();
} /**
*
* 描述:新增用户
* @author mao2080@sina.com
* @created 2017年5月9日 下午8:16:41
* @since
* @param request
* @return
* @throws BusinessException
*/
@RequestMapping("/deleteUser")
@ResponseBody
@AuthValidate(AuthCode.AU0002)
public ResObject deleteUser(HttpServletRequest request) throws BusinessException{
//业务代码
return new ResObject();
}
}
4、SpringMVC拦截器
package com.mao.interceptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView; import com.mao.auth.AuthCode;
import com.mao.auth.AuthValidate;
import com.mao.exception.BusinessException;
import com.mao.util.JsonUtil; /**
*
* 项目名称:---
* 模块名称:接入层
* 功能描述:用户登录拦截器(利用SpringMVC自定义拦截器实现)
* 创建人: mao2080@sina.com
* 创建时间:2017年4月25日 下午8:53:49
* 修改人: mao2080@sina.com
* 修改时间:2017年4月25日 下午8:53:49
*/
public class UserLoginInterceptor implements HandlerInterceptor { /**
*
* 描述:构造函数
* @author mao2080@sina.com
* @created 2017年4月28日 下午5:20:34
* @since
* @param accessService
*/
public UserLoginInterceptor() { } /**
*
* 描述:执行方法前
* @author mao2080@sina.com
* @created 2017年4月25日 下午9:01:44
* @since
* @param request HttpServletRequest
* @param response HttpServletResponse
* @param handler handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
try {
//校验登录
this.userLoginValidate(request);
//校验权限
this.userAuthValidate(request, handler);
} catch (Exception e) {
e.printStackTrace();
printMessage(response, e);
return false;
}
return true;
} /**
*
* 描述:输出到前端
* @author mao2080@sina.com
* @created 2017年4月28日 上午11:00:25
* @since
* @param response 响应
* @param res 对象
* @throws Exception
*/
public static void printMessage(HttpServletResponse response, Object res) throws Exception{
PrintWriter writer = null;
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html; charset=utf-8");
try {
writer = response.getWriter();
writer.print(JsonUtil.toJson(res));
} catch (Exception e) {
e.printStackTrace();
} finally {
if (writer != null){
writer.close();
}
}
} @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 { } /**
*
* 描述:用户登录校验
* @author mao2080@sina.com
* @created 2017年5月9日 下午8:27:25
* @since
* @param request
* @throws BusinessException
*/
private void userLoginValidate(HttpServletRequest request) throws BusinessException {
//校验代码
} /**
*
* 描述:用户权限校验
* @author mao2080@sina.com
* @created 2017年5月4日 下午8:34:09
* @since
* @param request HttpServletRequest
* @param handler
* @return
* @throws BusinessException
*/
private void userAuthValidate(HttpServletRequest request, Object handler) throws BusinessException {
AuthValidate validate = ((HandlerMethod) handler).getMethodAnnotation(AuthValidate.class);
if(validate == null){
throw new BusinessException("未配置自定义注解");
}
String funcCode = validate.value().getAuthCode();
if(funcCode.equals(AuthCode.Allow.getAuthCode())){
return;
}
String authId = validate.value().getAuthId();
List<String> auths = new ArrayList<>();//模拟从缓存或者从数据库中查询出对应用户的权限
if(!auths.contains(authId)){
throw new BusinessException("权限不足");
}
} }
5、拦截器配置
package com.mao.interceptor; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; /**
*
* 项目名称:---
* 模块名称:接入层
* 功能描述:拦截器配置
* 创建人: mao2080@sina.com
* 创建时间:2017年5月9日 下午8:54:00
* 修改人: mao2080@sina.com
* 修改时间:2017年5月9日 下午8:54:00
*/
@Configuration
@ComponentScan(basePackages={"com.mao"})
@EnableWebMvc
public class WebConfiguration extends WebMvcConfigurerAdapter { /**日志*/
private static final Log loger = LogFactory.getLog(WebConfiguration.class); /**
*
* 描述:构造函数
* @author mao2080@sina.com
* @created 2017年5月3日 下午4:48:41
* @since
*/
public WebConfiguration() {
loger.info("开启系统登录拦截");
} /**
*
* 描述:添加拦截器
* @author mao2080@sina.com
* @created 2017年4月25日 下午8:50:54
* @since
* @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
this.excludeUserLogin(registry.addInterceptor(new UserLoginInterceptor()));
} /**
*
* 描述:拦截请求
* @author mao2080@sina.com
* @created 2017年5月9日 下午8:55:28
* @since
* @param registration
*/
public void excludeUserLogin(InterceptorRegistration registration){
registration.addPathPatterns("/userController/*");
} }
6、返回对象
package com.mao.beans; import java.io.Serializable; /**
*
* 项目名称:
* 模块名称:
* 功能描述:
* 创建人: mao2080@sina.com
* 创建时间:2017年5月3日 下午6:37:11
* 修改人: mao2080@sina.com
* 修改时间:2017年5月3日 下午6:37:11
*/
public class ResObject implements Serializable{ /**序列号*/
private static final long serialVersionUID = 589903502110209046L; /**返回代码*/
private int code = 200; /**返回信息*/
private String desc = "Success."; /**返回数据*/
private Object data; /**
*
* 构建函数
* @author mao2080@sina.com
* @created 2017年3月24日 下午4:25:23
* @since
*/
public ResObject() { } /**
*
* 描述:构造函数
* @author mao2080@sina.com
* @created 2017年4月18日 下午3:32:26
* @since
* @param data 数据
*/
public ResObject(Object data) {
super();
this.data = data;
} /**
*
* 构建函数
* @author mao2080@sina.com
* @created 2017年3月24日 下午4:25:35
* @since
* @param code 返回代码
* @param desc 返回信息
*/
public ResObject(int code, String desc) {
super();
this.code = code;
this.desc = desc;
} /**
*
* 构建函数
* @author mao2080@sina.com
* @created 2017年3月24日 下午4:25:39
* @since
* @param code 返回代码
* @param desc 返回信息
* @param data 返回数据
*/
public ResObject(int code, String desc, Object data) {
super();
this.code = code;
this.desc = desc;
this.data = data;
} public Object getData() {
return data;
} public void setData(Object data) {
this.data = data;
} public int getCode() {
return code;
} public void setCode(int code) {
this.code = code;
} public String getDesc() {
return desc;
} public void setDesc(String desc) {
this.desc = desc;
} }
ResObject
7、异常类
package com.mao.exception; /**
*
* 项目名称:---
* 模块名称:接入层
* 功能描述:异常类
* 创建人: mao2080@sina.com
* 创建时间:2017年5月9日 下午8:22:21
* 修改人: mao2080@sina.com
* 修改时间:2017年5月9日 下午8:22:21
*/
public class BusinessException extends Exception{ public BusinessException() { } public BusinessException(String message) {
super(message);
} }
BusinessException
8、json工具类
package com.mao.util; import com.alibaba.dubbo.common.utils.StringUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.mao.exception.BusinessException; /**
*
* 项目名称:---
* 模块名称:常用工具类
* 功能描述:json工具类
* 创建人: mao2080@sina.com
* 创建时间:2017年3月28日 上午11:56:15
* 修改人: mao2080@sina.com
* 修改时间:2017年3月28日 上午11:56:15
*/
public class JsonUtil { /**
*
* 描述:将对象格式化成json字符串
* @author mao2080@sina.com
* @created 2017年4月1日 下午4:38:18
* @since
* @param object 对象
* @return json字符串
* @throws BusinessException
*/
public static String toJson(Object object) throws BusinessException {
try {
return JSON.toJSONString(object, new SerializerFeature[] {
SerializerFeature.WriteMapNullValue,
SerializerFeature.DisableCircularReferenceDetect,
SerializerFeature.WriteNonStringKeyAsString });
} catch (Exception e) {
throw new BusinessException();
}
} /**
*
* 描述:将对象格式化成json字符串(PrettyFormat格式)
* @author mao2080@sina.com
* @created 2017年4月1日 下午4:38:18
* @since
* @param object 对象
* @return json字符串
* @throws BusinessException
*/
public static String toJsonFormat(Object object) throws BusinessException {
try {
return JSON.toJSONString(object, new SerializerFeature[] {
SerializerFeature.WriteMapNullValue,
SerializerFeature.PrettyFormat,
SerializerFeature.DisableCircularReferenceDetect,
SerializerFeature.WriteNonStringKeyAsString });
} catch (Exception e) {
throw new BusinessException();
}
} /**
*
* 描述:转Map
* @author mao2080@sina.com
* @created 2017年4月1日 下午5:00:20
* @since
* @param obj 对象
* @return object
* @throws BusinessException
*/
public static Object toJsonObject(Object obj) throws BusinessException {
try {
return JSON.toJSON(obj);
} catch (Exception e) {
throw new BusinessException();
}
} /**
*
* 描述:将json串转为对象
* @author mao2080@sina.com
* @created 2017年4月1日 下午5:01:23
* @since
* @param jsonString json串
* @param clazz 对象
* @return
* @throws BusinessException
*/
public static <T> T fromJson(String jsonString, Class<T> clazz) throws BusinessException {
try {
if (StringUtils.isBlank(jsonString)) {
return null;
}
return (T) JSON.parseObject(jsonString, clazz);
} catch (Exception e) {
throw new BusinessException();
}
} /**
*
* 描述:暂时不开通
* @author mao2080@sina.com
* @created 2017年4月1日 下午5:08:12
* @since
* @param jsonString
* @return
* @throws Exception
*/
@SuppressWarnings("unused")
private static <T> T fromJson(String jsonString) throws Exception {
return JSON.parseObject(jsonString, new TypeReference<T>() {
}, new Feature[0]);
} }
JsonUtil
SpringMVC拦截器+Spring自定义注解实现权限验证的更多相关文章
- struts2拦截器加自定义注解实现权限控制
https://blog.csdn.net/paul342/article/details/51436565 今天结合Java的Annotation和Struts2进行注解拦截器权限控制. 功能需求: ...
- SpringMVC拦截器2(资源和权限管理)(作为补充说明)
SpringMVC拦截器(资源和权限管理) 1.DispatcherServlet SpringMVC具有统一的入口DispatcherServlet,所有的请求都通过DispatcherServle ...
- SpringMVC(9)实现注解式权限验证
对大部分系统来说都需要权限管理来决定不同用户可以看到哪些内容,那么如何在Spring MVC中实现权限验证呢?当然我们可以继续使用servlet中的过滤器Filter来实现.但借助于Spring MV ...
- Spring MVC基础知识整理➣拦截器和自定义注解
概述 Spring MVC中通过注解来对方法或者类进行动态的说明或者标注,类似于配置标识文件的属性信息.当标注的类或者方式被使用时候,通过提取注解信息来达到对类的动态处理.在 MVC中,我们常用的注解 ...
- [Java]利用拦截器和自定义注解做登录以及权限验证
1.自定义注解 需要验证登录的注解 package com.etaofinance.wap.common; import java.lang.annotation.Documented; import ...
- 拦截器和自定义注解@interface
1 .拦截器(Interceptor): 用于在某个方法被访问之前进行拦截,然后在Handler执行之前或之后加入某些操作,其实就是AOP的一种实现策略. 拦截用户的请求并进行相应的处理,比如:判断用 ...
- SpringBoot 拦截器和自定义注解判断请求是否合法
应用场景举例: 当不同身份的用户请求一个接口时,用来校验用户某些身份,这样可以对单个字段数据进行精确权限控制,具体看代码注释 自定义注解 /** * 对比请求的用户身份是否符合 * @author l ...
- SpringMVC拦截器和@ResponseBody注解冲突
在使用@ResponseBody注解后controller方法只会返回ModelandView对象的数据模型,不会返回视图,这样有很多好处,但是如果在拦截器中进行了页面转发,在满足页面转发条件时,不会 ...
- SpringMVC(10)实现注解式权限验证
在项目中如何处理出现的异常,在每个可能出现异常的地方都写代码捕捉异常?这显然是不合理的,当项目越来越大是也是不可维护的.那么如何保证我们处理异常的代码精简且便于维护呢?这就是本篇要讲的内容->异 ...
随机推荐
- redis 小结三-数据类型
redis 的数据类型主要有五种 字符串(String) 哈希表(Hash) 列表(List) 集合(Set ) 有序集合(Sorted Set) 1. 字符串 一个 key 对应一个 value 该 ...
- json格式和对象类型的转换20170330
(1)对象的类型转换成字符串类型(或者更确切的说是json类型的) JSONObject jo = JSONObject.fromObject(map);常见的java代码转换成json 比如:后台J ...
- linux:用户和组文件解释(/etc/passwd、/etc/shadow、/etc/group、/etc/gshadow)
一.用户文件:/etc/passwd [root@pinfun6 ~]# cat /etc/passwd root:x:0:0:root:/root:/bin/bash 1 2 3 4 5 6 7 | ...
- 如何在一个线程环境中使用一个线程非安全的java类
在开发过程中 当我们拿到一个线程非安全的java类的时候,我们可以额外创建这个类的管理类 并在管理类中控制同步 比如 一个非线程安全的Pair类 package test.thread.sx.test ...
- Eclipse创建Maven多模块工程Module开发(图文教程)
自己研究了下Eclipse用Maven多模块工程Module开发,跟大家分享一下! 功能模块来分Module,跟java的package类似,一般是按照的功能模块分module,比如:sso/cas/ ...
- QtSpim使用Tips
QtSpim使用记录 垃圾QtSpim,输入中文会死机 MIPS的中文资料奇缺,如果有问题建议google参考英文资料,许多外国大学的网站上有对MIPS各方面的详细介绍 QtSpim是MIPS处理器的 ...
- 090、ELK完成部署和使用 (2019-05-13 周二)
参考https://www.cnblogs.com/CloudMan6/p/7787870.html 上节我们已经部署了容器化的ELK,本节我们学习如何将日志导入ELK并进行图形化展示. 几乎 ...
- uni-app如何编写底部导航栏
在pages.json中配置代码如下: { "pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocat ...
- redis、rabitmq对比
redis.rabitmq对比 原文地址 简要介绍 RabbitMQ RabbitMQ是实现AMQP(高级消息队列协议)的消息中间件的一种,最初起源于金融系统,用于在分布式系统中存储转发消息,在易用性 ...
- hackthebox通关手记(持续更新)
简介: 花了点时间弄了几道题目.以前我是用windows渗透居多,在kali linux下渗透测试一直不怎么习惯.通过这几天做这些题目感觉顺手多了.有些题目脑洞也比较大,感觉很多也不适合于实际的环境 ...