特别提示:本人博客部分有参考网络其他博客,但均是本人亲手编写过并验证通过。如发现博客有错误,请及时提出以免误导其他人,谢谢!欢迎转载,但记得标明文章出处:http://www.cnblogs.com/mao2080/

设计思路

主要针对需要登录后操作的接口进行校验。接入层在对外暴露接口后,网页、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自定义注解实现权限验证的更多相关文章

  1. struts2拦截器加自定义注解实现权限控制

    https://blog.csdn.net/paul342/article/details/51436565 今天结合Java的Annotation和Struts2进行注解拦截器权限控制. 功能需求: ...

  2. SpringMVC拦截器2(资源和权限管理)(作为补充说明)

    SpringMVC拦截器(资源和权限管理) 1.DispatcherServlet SpringMVC具有统一的入口DispatcherServlet,所有的请求都通过DispatcherServle ...

  3. SpringMVC(9)实现注解式权限验证

    对大部分系统来说都需要权限管理来决定不同用户可以看到哪些内容,那么如何在Spring MVC中实现权限验证呢?当然我们可以继续使用servlet中的过滤器Filter来实现.但借助于Spring MV ...

  4. Spring MVC基础知识整理➣拦截器和自定义注解

    概述 Spring MVC中通过注解来对方法或者类进行动态的说明或者标注,类似于配置标识文件的属性信息.当标注的类或者方式被使用时候,通过提取注解信息来达到对类的动态处理.在 MVC中,我们常用的注解 ...

  5. [Java]利用拦截器和自定义注解做登录以及权限验证

    1.自定义注解 需要验证登录的注解 package com.etaofinance.wap.common; import java.lang.annotation.Documented; import ...

  6. 拦截器和自定义注解@interface

    1 .拦截器(Interceptor): 用于在某个方法被访问之前进行拦截,然后在Handler执行之前或之后加入某些操作,其实就是AOP的一种实现策略. 拦截用户的请求并进行相应的处理,比如:判断用 ...

  7. SpringBoot 拦截器和自定义注解判断请求是否合法

    应用场景举例: 当不同身份的用户请求一个接口时,用来校验用户某些身份,这样可以对单个字段数据进行精确权限控制,具体看代码注释 自定义注解 /** * 对比请求的用户身份是否符合 * @author l ...

  8. SpringMVC拦截器和@ResponseBody注解冲突

    在使用@ResponseBody注解后controller方法只会返回ModelandView对象的数据模型,不会返回视图,这样有很多好处,但是如果在拦截器中进行了页面转发,在满足页面转发条件时,不会 ...

  9. SpringMVC(10)实现注解式权限验证

    在项目中如何处理出现的异常,在每个可能出现异常的地方都写代码捕捉异常?这显然是不合理的,当项目越来越大是也是不可维护的.那么如何保证我们处理异常的代码精简且便于维护呢?这就是本篇要讲的内容->异 ...

随机推荐

  1. python-day17(正式学习)

    目录 包 一.什么是包? 二.为什么要有包? 三.如何用包? 3.1 模块和包 3.2 扩展模块功能 3.3 修改__init__.py文件 绝对导入和相对导入 注意事项 模块不来总结了,直接去htt ...

  2. Codeforces 1220D. Alex and Julian

    传送门 首先考虑怎样的集合一定是合法的 发现全部是奇数的集合一定合法,因为每次都是奇数连偶数,偶数连奇数 然后考虑如果集合同时有奇数和偶数是否一定不合法,结论是一定不合法,证明如下: 设某个奇数为 $ ...

  3. 作业调度框架Quartz.NET-现学现用-02-任务监听 - 简书

    原文:作业调度框架Quartz.NET-现学现用-02-任务监听 - 简书 前言 任务调度系统并不是完美的,它会出现任务执行失败的情况.如果你需要处理任务失败后的逻辑,希望这篇笔记可以为你提供些帮助. ...

  4. C# ref out parase 理解

    这节课我们来学习方法中的参数传递,在面向对象二中,我曾说过,参数也属于变量的一种,在c语言的学习时,同学们都学习过参数这个概念和用法,方法使用参数列表来传递变量的基本语法如下:returnType  ...

  5. CTP报单参数详解

    交易所代码 产品类型 业务类型 价格类型 指令类型 价格类型 OrderPriceType 有效期类型 TimeCondition 成交量类型 VolumeCondition 备注 CZCE 郑商所 ...

  6. Java的GUI框架如何选择? Swing、SWT、AWT、SwingX、JGoodies、JavaFX、Apache Pivot、BeautyEye框架(美观)?

    AWT 是swing的基础,运行良好,但缺少高级组件.如果您打算创建丰富的应用程序,那么AWT可能不是最好的方法.但是对于不需要丰富用户界面的较小gui应用程序来说.这可能非常适合,因为它是一个久经考 ...

  7. 万兴神剪手 Wondershare Filmora v9.2.11.6 简体中文版

    目录 1. 介绍 2. 简体中文9.2.1.10汉化版下载 3. 安装和激活说明 1. 介绍 万兴神剪手 Filmora 是一款界面简洁时尚.功能强大的视频编辑软件,它是深圳万兴科技公司近年来的代表作 ...

  8. Ubuntu无法安装nginx

    1.问题Reading package lists... DoneBuilding dependency tree       Reading state information... DoneSom ...

  9. [工具] BurpSuite--XssValidator插件

    0x00 安装 所需软件: 1.burpsuite 2.xssvalidator 源码:https://github.com/nVisium/xssValidator(按照编译指导编译) burpsu ...

  10. php判断变量是否为数字is_numeric()

    is_numeric — 检测变量是否为数字或数字字符 <?php $tests = array( "31", 1380, "1e4", "no ...