Cookie、Token、Redis混合使用

来源:互联网 发布:汽车轮毂数据大全 编辑:程序博客网 时间:2024/06/05 15:15

在集群中,我们一般不会使用session,我们一般构造一个Cookie放入cookie和redis中。

Cookie的生命周期如果创建时不指定(也就是默认值<0),那么是指到浏览器关闭时,cookie就消失了。所以这里就要注意了,如果浏览器未关闭时,只要与应用程序有一次交互,就要延长redis中的token时间。否则就出现不管操作与不操作,在30分钟后都会找不到redis中的token,这就不合理了。

controller中doLogin()方法:

@RequestMapping(value = "doLogin", method = RequestMethod.POST)@ResponseBodypublic Map<String, Object> doLogin(User user, HttpServletRequest request, HttpServletResponse response) {Map<String, Object> map = new HashMap<>();try {String token = userService.doLogin(user.getUsername(), user.getPassword());if (StringUtils.isEmpty(token)) {map.put("status", 500);return map;}CookieUtils.setCookie(request, response, TOKEN_NAME, token);map.put("status", 200);} catch (Exception e) {map.put("status", 500);e.printStackTrace();return map;}return map;}
这里没有使用Restful格式,所以状态200或500都是业务状态,不是http状态。
个人理解controller一般要去做try-catch,而service层要做抛异常操作。
返回类型为Map的话,对于前台json接收也是很方便的,data.xxx就是Map中get(xxx)的返回值。
controller中操作cookie(写cookie,名为自定义,值为token)
service中操作校验以及redis存储。这里redis不在作为缓存,而是作为数据库,所以它和业务是绑定的,即:如果redis报错,业务也应报错。而不像缓存。
service方法:
public String doLogin(String username, String password) throws Exception {User record = new User();record.setUsername(username);User user = userMapper.selectOne(record);if (user == null) {return null;}if (!StringUtils.equals(DigestUtils.md5Hex(password), user.getPassword())) {return null;}String token = DigestUtils.md5Hex(username + System.currentTimeMillis());redisService.set("TOKEN_" + token, user, 30L);return token;}
如果我们在做redis存user对象时,不想序列化password,那么只要在User类上的password上加@JsonIgnore。用这种方式要求restTemplate的泛型为<String,String>并结合ObjectMapper的writeValueAsString和readValue比较好。

当有与应用程序交互时,可以在过滤器或拦截器中使用redisService.expire("TOKEN_" + token, 30L);(redisTemplate.expire(key, minutes, TimeUnit.MINUTES);)
当退出应用程序时,controller层删除cookie(时间设为0),service层删除redis中的token对应的user。







原创粉丝点击