服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服务器之家 - 编程语言 - JAVA教程 - App登陆java后台处理和用户权限验证

App登陆java后台处理和用户权限验证

2020-05-13 14:44梦想实现家-Tony JAVA教程

这篇文章主要为大家详细介绍了App登陆java后台处理和用户权限验证,感兴趣的朋友可以参考一下

最近做一个app项目,后台我独自一人开发,开发任务顺序安排上没有把登陆,注册和权限验证这些基本功能放在第一阶段开发,现在是部分业务相关功能已经完成,但是用户入口竟然还没有,只能说明当初需求分析的时候还是太过于着急了,把最基本的用户入口给放到后面了。

现在就需要在现有代码的基础上添加用户登录和权限验证功能。

关于登录和权限验证方面,参照以前做iOS的开发经验,App端提供用户名和密码换取token,每次通过换取的token请求需要登陆权限的操作。

现在反过来,我就需要考虑下面几个问题:

1.在现有功能的代码上如何比较轻松地满足这些功能的实现,使得现有代码改动不大,并且今后新功能实现权限验证不麻烦

2.如何根据用户名和密码生成token,并且在需要权限的功能上如何区分客户端提供token的正确性

首先面对第一个问题,根据经验,常规解决方案就是过滤器,拦截器,若是在需求安排上登陆和权限验证这些放在前面的话,只要让后期功能的url有一定规律,过滤器或拦截器的使用简直屡试不爽。但是我现在面对的是前期没有任何设计和规范的url,所以使用过滤器或者拦截器是我不愿意面对的。

除了以上常规解决方案,spring AOP正好成了解决这类问题的利器,利用面相切面编程对所有需要权限验证的method做一个前置通知,但是由于url,类名或者方法没有规律,于是我想到了自定义注解(annotation),对所有加上自定义注解的method做权限验证。

1.既然已经想到使用spring aop了,那首先第一步就是在spring配置文件中开启aop

//开启aop

<aop:aspectj-autoproxy />

以上配置基于项目中倒入spring-aop相关jar包,并且在配置文件头部引入aop的url

2.其次我们先定义一个自定义annotation

?
1
2
3
4
5
6
7
8
9
@Target({ElementType.METHOD, ElementType.TYPE})
 
@Retention(RetentionPolicy.RUNTIME)
 
public @interface UserAccess {
 
 
 
}
 

3.我们还不能急于做权限验证的功能,因为现在我们的token还没有生成方案。

在token生成上考虑到单点登录,所以token不能一直固定,否则在任何时候,只要拥有token就可以同时至少两个人使用同一个帐户,这是目前我们业务上不允许的。最终我选择了”username+password+登录时间“做MD5加密作为token(在保证唯一和可变的情况下,有很多方法,比如uuid)。在验证用户名和密码成功的情况下生成token,并将token以“username:token” 和 “token:用户”的键值对形式保存起来(也可以保存进数据库),最后返回token给客户端。

以下代码只做一个简单示例:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
@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做实验:

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
@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就是一个很好的切入点

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
@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("没有权限");
 
}
 
}
 
}
 

至此,登陆和权限验证功能全部完成。

另外附上个人github上面的源码:https://github.com/zw201913/applogin.git

以上就是本文的全部内容,希望对大家的学习有所帮助。

延伸 · 阅读

精彩推荐