此文已由作者赵计刚授权网易云社区发布。

欢迎访问网易云社区,了解更多网易技术产品运营经验。

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的细节与解决方案,以后再说!

此文已由作者赵计刚授权网易云社区发布。

欢迎访问网易云社区,了解更多网易技术产品运营经验。

相关文章:
【推荐】 网易云基于 Kubernetes 的深度定制化实践
【推荐】 【工程实践】服务器数据解析
【推荐】 The Beam Model:Stream & Tables翻译(上)

企业项目开发--cookie(3)的更多相关文章

  1. 企业项目开发--cookie(1)

    此文已由作者赵计刚授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 注:本章代码基于<第五章 企业项目开发--mybatis注解与xml并用>的代码,链接如下: h ...

  2. 第六章 企业项目开发--cookie

    注:本章代码基于<第五章 企业项目开发--mybatis注解与xml并用>的代码,链接如下: http://www.cnblogs.com/java-zhao/p/5120792.html ...

  3. 企业项目开发--cookie(2)

    此文已由作者赵计刚授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 2.1.3.CookieUtil:(cookie的基本操作:增删查,注意没有改)  1 package co ...

  4. 第八章 企业项目开发--分布式缓存memcached

    注意:本节代码基于<第七章 企业项目开发--本地缓存guava cache> 1.本地缓存的问题 本地缓存速度一开始高于分布式缓存,但是随着其缓存数量的增加,所占内存越来越大,系统运行内存 ...

  5. 企业项目开发--分布式缓存memcached(3)

    此文已由作者赵计刚授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 3.3.ssmm0-data 结构: 3.3.1.pom.xml  1 <?xml version=& ...

  6. 第十一章 企业项目开发--消息队列activemq

    注意:本章代码基于 第十章 企业项目开发--分布式缓存Redis(2) 代码的github地址:https://github.com/zhaojigang/ssmm0 消息队列是分布式系统中实现RPC ...

  7. 企业项目开发--分布式缓存Redis

    第九章 企业项目开发--分布式缓存Redis(1) 注意:本章代码将会建立在上一章的代码基础上,上一章链接<第八章 企业项目开发--分布式缓存memcached> 1.为什么用Redis ...

  8. 第九章 企业项目开发--分布式缓存Redis(1)

    注意:本章代码将会建立在上一章的代码基础上,上一章链接<第八章 企业项目开发--分布式缓存memcached> 1.为什么用Redis 1.1.为什么用分布式缓存(或者说本地缓存存在的问题 ...

  9. 第十章 企业项目开发--分布式缓存Redis(2)

    注意:本章代码是在上一章的基础上进行添加修改,上一章链接<第九章 企业项目开发--分布式缓存Redis(1)> 上一章说了ShardedJedisPool的创建过程,以及redis五种数据 ...

随机推荐

  1. Windows使用SSH Secure Shell实现免密码登录CentOS

    笔记来自:http://blog.csdn.net/jiangshouzhuang/article/details/50683049 1.在Windows上生成密钥找到Secure Shell Cli ...

  2. java.security.cert.CertificateException: No subject alternative names matching IP address xxx.xxx.xxx.xxx found

    https与http不同的是,https加密,需要验证证书,而http不需要. 在连接的代码中加上: static { disableSslVerification(); } private stat ...

  3. jsp里面不能使用${pageContext.request.contextPath}解决方案

    1.在jsp中使用${pageContext.request.contextPath}获取相对路径,可是最后路径变为:http://localhost:8080/oneself/$%7BpageCon ...

  4. 2018.11.05 bzoj2143: 飞飞侠(最短路)

    传送门 最短路好题. 考虑对每个二维坐标建立一个高度属性. 这样每次如果在点(i,j,0)(i,j,0)(i,j,0)只能选择花费bi,jb_{i,j}bi,j​跳向(i,j,ai,j)(i,j,a_ ...

  5. maven 中央仓库地址 随笔记下了

    Maven 中央仓库地址: 1. http://www.sonatype.org/nexus/ 2. http://mvnrepository.com/ 3. http://repo1.maven.o ...

  6. python中下划线

    引用:https://blog.csdn.net/tcx1992/article/details/80105645?from=timeline Python中下划线的5种含义 class A(obje ...

  7. python模块:sys

    # encoding: utf-8 # module sys # from (built-in) # by generator 1.145 """ This module ...

  8. 用IrisSkin2.dll美化你的WinForm

    From:http://hi.baidu.com/tr0j4n 在WinForm中,可以方便地给自己的程序添加皮肤,做出各种绚丽的效果,而只需要很简单的几句代码即可搞定,下面来领略下. 前期准备:1. ...

  9. python输出显示颜色

    显示颜色格式:\033[显示方式;字体色;背景色m......[\033[0m] ------------------------------------------- --------------- ...

  10. 大压力下Redis参数调整要点

    调整以下参数,可以大幅度改善Redis集群的稳定性: 为何大压力下要这样调整? 最重要的原因之一Redis的主从复制,两者复制共享同一线程,虽然是异步复制的,但因为是单线程,所以也十分有限.如果主从间 ...