通过自定义注解或拦截器实现APP调用后接口全局权限验证
来源:互联网 发布:阿里云 域名查询 编辑:程序博客网 时间:2024/06/05 16:21
现在就需要在现有代码的基础上添加用户登录和权限验证功能。
关于登录和权限验证方面,参照以前做iOS的开发经验,App端提供用户名和密码换取token,每次通过换取的token请求需要登陆权限的操作。
现在反过来,我就需要考虑下面几个问题:
1.在现有功能的代码上如何比较轻松地满足这些功能的实现,使得现有代码改动不大,并且今后新功能实现权限验证不麻烦
2.如何根据用户名和密码生成token,并且在需要权限的功能上如何区分客户端提供token的正确性
首先面对第一个问题,根据经验,常规解决方案就是过滤器,拦截器,若是在需求安排上登陆和权限验证这些放在前面的话,只要让后期功能的url有一定规律,过滤器或拦截器的使用简直屡试不爽。但是我现在面对的是前期没有任何设计和规范的url,所以使用过滤器或者拦截器是我不愿意面对的。
除了以上常规解决方案,spring AOP正好成了解决这类问题的利器,利用面相切面编程对所有需要权限验证的method做一个前置通知,但是由于url,类名或者方法没有规律,于是我想到了自定义注解(annotation),对所有加上自定义注解的method做权限验证。
1.既然已经想到使用spring aop了,那首先第一步就是在spring配置文件中开启aop以及加AOP相关标签
//开启aop
<aop:aspectj-autoproxy />
//加AOP相关标签
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"
以上配置基于项目中倒入spring-aop相关jar包,并且在配置文件头部引入aop的url
2.其次我们先定义一个自定义annotation
package cn.uce.suc.bkg.control.infomon;import java.lang.annotation.Retention;import java.lang.annotation.Target;@Target({java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.TYPE})@Retention(java.lang.annotation.RetentionPolicy.RUNTIME)public @interface UserAccess {}3.我们还不能急于做权限验证的功能,因为现在我们的token还没有生成方案。
在token生成上考虑到单点登录,所以token不能一直固定,否则在任何时候,只要拥有token就可以同时至少两个人使用同一个帐户,这是目前我们业务上不允许的。最终我选择了”username+password+登录时间“做MD5加密作为token(在保证唯一和可变的情况下,有很多方法,比如uuid)。在验证用户名和密码成功的情况下生成token,并将token以“username:token” 和 “token:用户”的键值对形式保存起来(也可以保存进数据库),最后返回token给客户端。以下代码只做一个简单示例:
@Service public class LoginService { /** * 存放“用户名:token”键值对 */ public static Map<String,String> tokenMap=new HashMap<String,String>(); /** * 存放“token:User”键值对 */ public static Map<String,User> loginUserMap=new HashMap<String,User>(); public String login(String name,String password){ System.out.println(name+"-----"+password); /** * 判断是否登录成功 * 1.登录成功 * 1.1.成功生成对应的token并更新 * 1.2.失败就抛异常 */ String token=tokenMap.get(name); User user=null; if(token==null){ user=new User(); user.setName(name); user.setPassword(password); System.out.println("新用户登录"); }else{ user=loginUserMap.get(token); loginUserMap.remove(token); System.out.println("更新用户登录token"); } token=MD5Util.MD5(name+password+new Date().getTime()); loginUserMap.put(token, user); tokenMap.put(name, token); System.out.println("目前有"+tokenMap.size()+"个用户"); for(User u:loginUserMap.values()){ System.out.println(u.getName()+":"+u.getPassword()); } return token; } }4.于此同时,我们的客户端登陆后也就获得了token,只要在所有需要权限的请求中携带token即可成功获取响应(建议:为方便app编码,token可携带在请求头中,现有代码就无需大改动,并且今后都不需要关心token的问题)。我随便找了个method做实验:
@Controller @RequestMapping("/login") public class LoginController { @Autowired private LoginService loginService; @UserAccess @RequestMapping(value="/loginin",method=RequestMethod.GET) public @ResponseBody String login(HttpServletRequest request){ String name=request.getParameter("name"); String password=request.getParameter("password"); String token=loginService.login(name, password); return token; } }注意加粗部分就是自定义annotation,登陆功能的请求参数是不可能有token的,所以不管验证多少次,都不可能通过,只是做个示例。@UserAccess添加在需要权限验证的功能上才起作用
5.现在自定义annotation就是一个很好的切入点
@Component @Aspect public class PermissionAspect { //设置以自定义annotation作为切入点 @Before("@annotation(com.example.chap01.annotation.UserAccess)") public void checkPermission(JoinPoint joinPoint) throws Exception{ System.out.println("前置通知"); //获取拦截的请求参数 Object[] args = joinPoint.getArgs(); HttpServletRequest request=(HttpServletRequest)args[0]; String token=request.getParameter("token"); System.out.println("前置通知 token:"+token); User user=LoginService.loginUserMap.get(token); if(user==null){ System.out.println("验证不通过!"); throw new Exception("没有权限"); } } }
- 通过自定义注解或拦截器实现APP调用后接口全局权限验证
- springboot + 拦截器 + 注解 实现自定义权限验证
- SpringMVC拦截器+Spring自定义注解实现权限验证
- 自定义注解+拦截器实现权限控制
- 自定义注解+拦截器实现权限控制
- 利用struts2拦截器加自定义注解实现权限控制
- 自定义注解+Struts2拦截器实现简单权限控制
- SpringBoot使用自定义注解实现权限拦截
- 通过注解实现调用指定的拦截器
- 自定义注解,实现拦截器
- spring boot 自定义注解实现权限验证
- sparingmvc自定义拦截器做权限验证
- Struts 拦截器权限控制【通过拦截器实现登录后跳转到登录前页面】
- Struts 拦截器权限控制【通过拦截器实现登录后跳转到登录前页面】
- Struts 拦截器权限控制【通过拦截器实现登录后跳转到登录前页面】
- Struts 拦截器权限控制【通过拦截器实现登录后跳转到登录前页面】
- 使用注解方式调用自定义拦截器
- 用拦截器,注解实现权限
- Spring boot入门
- antd icon离线无法显示 和引入官方库后覆盖原样式问题
- jQuery选择器总结
- Docker学习记录(4)——docker pull默认从本地镜像仓库拉取镜像
- dojo.cookie("appid") && dojo.cookie("appid", null, {path: '/', expires: -1});
- 通过自定义注解或拦截器实现APP调用后接口全局权限验证
- thinkphp将数据库表导出excel phpexcel
- 叨逼叨
- JSONP实例
- obs-studio模块简介与源码编译
- 导出数据库时候: UDE-12541: operation generated ORACLE error 12541ORA-12541: TNS:no listener
- Springmvc学习(03)-Spring && SpringMVC && MyBatis整合
- Python实现SMO算法
- 支持向量机(1)-概念及推导