此文已由作者赵计刚授权网易云社区发布。
欢迎访问网易云社区,了解更多网易技术产品运营经验。
2.2.3、AdminController
1 package com.xxx.web.admin;
2
3 import java.util.List;
4
5 import javax.servlet.http.HttpServletRequest;
6 import javax.servlet.http.HttpServletResponse;
7
8 import org.springframework.beans.factory.annotation.Autowired;
9 import org.springframework.stereotype.Controller;
10 import org.springframework.web.bind.annotation.RequestMapping;
11 import org.springframework.web.bind.annotation.RequestParam;
12 import org.springframework.web.bind.annotation.ResponseBody;
13 import org.springframework.web.servlet.ModelAndView;
14
15 import com.xxx.model.userManagement.Admin;
16 import com.xxx.service.userManagement.AdminService;
17 import com.xxx.util.admin.AdminCookieUtil;
18
19 /**
20 * adminController
21 */
22 @Controller
23 @RequestMapping("/admin")
24 public class AdminController {
25
26 @Autowired
27 private AdminService adminService;
28
29 /**
30 * 管理员注册
31 */
32 @ResponseBody
33 @RequestMapping("/register")
34 public boolean register(@RequestParam("username") String username,
35 @RequestParam("password") String password){
36 Admin admin = new Admin();
37 admin.setUsername(username);
38 admin.setPassword(password);
39
40 boolean isRegisterSuccess = adminService.register(admin);
41
42 return isRegisterSuccess;
43 }
44
45 /**
46 * 管理员登录
47 */
48 @RequestMapping("/login")
49 public ModelAndView login(@RequestParam("username") String username,
50 @RequestParam("password") String password,
51 HttpServletResponse response){
52
53
54 Admin admin = adminService.login(username, password);
55
56 ModelAndView modelAndView = new ModelAndView();
57 if(admin == null){
58 modelAndView.addObject("message", "用户不存在或者密码错误!请重新输入");
59 modelAndView.setViewName("error");
60 }else{
61 modelAndView.addObject("admin", admin);
62 modelAndView.setViewName("userinfo");
63 /*
64 * 这为什么不直接传一个username,而传了一个admin,
65 * 是因为在实际开发中,你传过去的信息可能不只是username,还有用户手机号、地址等等
66 */
67 AdminCookieUtil.addLoginCookie(admin, response);
68 }
69
70 return modelAndView;
71 }
72
73 /*****************************mybatis xml方式解决的问题*******************************/
74 /**
75 * 根据username或password查找List<Admin>
76 */
77 @ResponseBody
78 @RequestMapping("/findAdmin")
79 public List<Admin> findAdmin(@RequestParam(value="username",required=false) String username,
80 @RequestParam(value="password",required=false) String password,
81 @RequestParam("start") int start,
82 @RequestParam("limit") int limit,
83 HttpServletRequest request){
84 Admin admin = AdminCookieUtil.getLoginCookie(request);
85 if(admin == null){//未登录
86 return null;
87 }
88 List<Admin> adminList = adminService.findAdmin(username, password, start, limit);
89 return adminList;
90 }
91
92 /**
93 * 插入一个用户并返回主键
94 * 注意:get请求也会自动装配(即将前台传入的username和password传入admin)
95 */
96 @ResponseBody
97 @RequestMapping("/insert")
98 public Admin insertAdminWithBackId(Admin admin){
99 return adminService.insertAdminWithBackId(admin);
100 }
101 }说明,这个类只修改了两个方法login()和findAdmin()。
测试:
向浏览器写入cookie

从浏览器读cookie

注意:
上述我们发了两个cookie,其中username的value没有加密,是因为这个value不是私密数据且我们在前台会直接使用,这样的话,省去了js解密的过程。
对于allinfo的加密是为了在浏览器端不让用户将cookie看的那么明显,保护一些私密数据;或者在整个传输过程中,即使被窃听者获取了,也难以知道其中的cookie值。但是,如果窃听者获取了allinfo这个cookie后,就可以使用这个cookie模拟登录然后做一些操作,这个不知道cookie机制会怎样解决?(答案见最下方)
对于allinfo的加密而言,仅使用AES加密事实上也不太合适,因为如果窃听者窃听到你的cookie后,对其进行篡改,当请求头再将这些信息传递过来的时候,可能经过json转化后就会是另一个Admin的信息了,如果需要防止这种情况发生,需要同时对cookie值进行消息摘要加密了(具体的消息摘要加密可以参照"Java加密与解密"系列博客),当然,在绝大多数情况下,如果窃听者不知道你的cookie值得话,如果他对这个值进行了随意的篡改,那么将来在将这个值进行解密后,对其转化成json的过程中就会抛出异常,因为解密后的json串很可能就不符合json的格式了,所以绝大多数情况下,仅适用于AES是可行的。
对于cookie的name实际上也应该加密,加密后浏览器端或窃听者截到的cookie他就不知道是什么意思了,这个加密非常简单,直接在线下使用SHA256出一个字符串或者就使用上边所讲的AES的生成key的方法生成一个就好,然后写在name中,代码再列一遍:
String key = Base64.encodeBase64String(AESUtil.getKey());
cookie不可以在多种浏览器之间共享,因为每个浏览器存cookie路径不是一样的
同一种浏览器,多个标签页共享的话,需要再生成cookie的时候添加cookie的有效期;否则cookie为会话cookie,这种客户端是不会把cookie存到硬盘上的,其他标签也无法获取到cookie
总结:
如果安全措施搞得好+cookie数量不多+cookie的总大小对带宽的占用可以接受,使用cookie(对于安全措施这一块,cookie被劫持的可能性一般不大,如果不是非常敏感的权限,可以使用记住我这些功能,如果对于敏感权限,例如金钱操作,就强制重新登录,类似于shiro)
对于浏览器禁用cookie的事情,基本可以不考虑,绝大多数现代浏览器都不会禁用cookie。
疑问:
如果被窃听者劫取到你的cookie,即使你对这些cookie做了加密,使其看不到cookie中的信息,但是其也可以通过该cookie模拟登录行为,然后获得一些权限,执行一些操作。(这是个疑问,记住我这个功能就是这样做的,怎样做到安全的呢?)
解答:方案
1、使用权限框架shiro
注意:shiroshiro保存了你的账户名(编码)和可记住密码的有效时间到cookie里,下次会把账户名带过来,可以允许执行一些非敏感操作。根据你后台设定的权限;当然对于敏感权限的话,一定要重新登录才行。(当然,由于还是存在cookie里,可能还是存在会被劫持的情况)
具体看下边图片:("记住我"的功能)

2、https(即使被劫取到,也不能重传)
这个是可以解决上边问题的,但是https没闹懂。
3、IP变动
1)客户端登陆的时候,记录客户端IP到数据库
2)下次登录从request中获取IP并与前一次记录的IP作对比,如果IP没有发生变化,则得直接进入已登录状态了;如果IP发生了变化,则重新登录,登录之后,修改IP
3)之后的过程如上
当然,对于以上这种方式,还有一种改进,就是将用户登录的IP放入缓存(当然可以指定缓存时间),这样每次就可以从缓存中查IP了。
但是这种方式有个问题,就是说同一台电脑换一个网络环境,这时候IP就变了,就得重新登陆了。
4、数字签名算法
数字签名的三个作用中的一个就是"认证数据来源",感觉这会是一个思路,但是具体怎么实现还没想好。如果大家有想好的,帮指点一下!
数字签名算法的具体实现见"Java加密与解密"《第十四章 数字签名算法--RSA》,链接如下:
http://www.cnblogs.com/java-zhao/p/5091363.html
有关于session的细节与解决方案,以后再说!
此文已由作者赵计刚授权网易云社区发布。
欢迎访问网易云社区,了解更多网易技术产品运营经验。
相关文章:
【推荐】 电商购物车产品在做什么?
【推荐】 Restify Api 开发经验