用cookie 和redis 实现登录,分布式session 的功能。
程序员文章站
2022-05-28 16:12:35
...
@GetMapping("/login2")
public Result<MiaoUser> login2(HttpServletResponse response , @CookieValue(value = MiaoUserService.COOKIENAME,required = false
)String tk
, @RequestParam(value = MiaoUserService.COOKIENAME,required = false) String cl,LoginVo loginVo) {
if (StringUtils.isEmpty(tk) && StringUtils.isEmpty(cl)) {
return Result.error(CodeMsg.ERROR);
}
System.out.println(loginVo);
String token = StringUtils.isEmpty(cl)?tk:cl;
MiaoUser user = miaoUserService.token(token);
return Result.success(user);
controller添加一个传cookie的请求。模拟登陆后
public MiaoUser token(String token) {
if (StringUtils.isEmpty(token)) {
return null;
}
return redisSer.get(UserKey.token, token, MiaoUser.class);
}
从redis 中取出token
public boolean id(HttpServletResponse
response, LoginVo loginVo) {
long id = Long.parseLong(loginVo.getMobile());
MiaoUser user = miaoUserDao.id(id);
if (user == null) {
throw new GlobalException(CodeMsg.MOBILE_NOT_EXIST);
}
String password = user.getPassword();
String salt = user.getSalt();
String second = MD5Utils.second(loginVo.getPassword() + "", salt);
if (!password.equals(second)) {
throw new GlobalException(CodeMsg.PASSWORD_NOT_EXIST);
}
String token = UUIDUtils.uuid();
redisSer.set(UserKey.token, token, user);
Cookie cookie = new Cookie(COOKIENAME
, token);
System.err.println(
UserKey.token.expireSec()
);
cookie.setMaxAge(UserKey.token.expireSec());
response.addCookie(cookie);
return true;
}
在登陆的过程中,我们利用随机数生成个token 然后用redis 把token存起来。 将token
用cookie的方式,添加到response中。然后浏览器下次请求就会有cookie。
以上这样实现存在一个问题,就是登陆的时间是从第一次开始登陆就开始算了。而不是从最后一次点击才开始算。这样会造成,用着用着就需要重新登陆了。
修改代码
将生成token 以及存入cookie提取成一个方法
private void addCookie(HttpServletResponse response, MiaoUser user) {
String token = UUIDUtils.uuid();
redisSer.set(UserKey.token, token, user);
Cookie cookie = new Cookie(COOKIENAME
, token);
System.err.println(
UserKey.token.expireSec()
);
cookie.setMaxAge(UserKey.token.expireSec());
response.addCookie(cookie);
}
在每次返回之前,我们又重新设置了cookie ,也重新生成了token,时间也是全新的。
以上的代码有个问题,如果每个方法都需要user 信息。我们需要在每个方法都要获取。重复太多
我们可以在之前的一步做统一的处理
在springMVC给参数赋值那一步做统一的处理。
package com.home.miaosha.config;
import com.home.miaosha.entity.CodeMsg;
import com.home.miaosha.entity.MiaoUser;
import com.home.miaosha.entity.Result;
import com.home.miaosha.service.MiaoUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Service
public class UserArgumentResolver implements HandlerMethodArgumentResolver {
@Autowired
MiaoUserService miaoUserService;
@Override
public boolean supportsParameter(MethodParameter methodParameter) {
Class<?> clazz = methodParameter.getParameterType();//判断Class 类型的对象要要用== 来判断。
return clazz == MiaoUser.class;
}
//如果上面的方法为true 框架才会执行下面这个方法。
@Override
public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
HttpServletRequest request = nativeWebRequest.getNativeRequest(HttpServletRequest.class);
HttpServletResponse response = nativeWebRequest.getNativeResponse(HttpServletResponse.class);
String paramToken = request.getParameter(MiaoUserService.COOKIENAME);
Cookie[] cookies = request.getCookies();
String cookieToken=null;
for (Cookie cookie : cookies) {
if (cookie.getName().equals(MiaoUserService.COOKIENAME)) {
cookieToken = cookie.getValue();
}
}
if (StringUtils.isEmpty(paramToken) && StringUtils.isEmpty(cookieToken)) {
return null;
}
String token = StringUtils.isEmpty(paramToken)?cookieToken:paramToken;
MiaoUser user = miaoUserService.token(response,token);
return user;
}
}
这个是给参数赋值的方法。如何让框架自动运行这个方法呢?
配置类
package com.home.miaosha.config;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.boot.autoconfigure.web.ResourceProperties;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import java.util.List;
@Configuration
public class WebConfig implements WebMvcConfigurer{
@Autowired
UserArgumentResolver userArgumentResolver;
@Override
public void addInterceptors(InterceptorRegistry registry) {
}
//这个方法就是为controller的参数赋值的。框架会自动调用的。
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(userArgumentResolver);
}
}
这个是将自己的参数处理类,注册进mvc框架。自动调用。
controller中可以极大的简化
@GetMapping("/login3")
public Result<MiaoUser> login2(HttpServletResponse response ,LoginVo loginVo,MiaoUser miaoUser) {
System.out.println(miaoUser
);
return Result.success(miaoUser);
}
方法有业务无关的都可以审掉了。清晰。
上一篇: 第009讲:了不起的分支和循环3
推荐阅读
-
PHP 实现超简单的SESSION与COOKIE登录验证功能示例
-
用Python实现web端用户登录和注册功能的教程
-
.NET Core2.0+MVC 用Redis/Memory+cookie实现的sso单点登录
-
PHP cookie,session的使用与用户自动登录功能实现方法分析
-
session(登录注销)和cookie(记住用户名和密码)的实现
-
session(登录注销)和cookie(记住用户名和密码)的实现
-
php同时使用session和cookie来保存用户登录信息的实现代码_php实例
-
Django 用Session和Cookie分别实现记住用户登录状态
-
用cookie 和redis 实现登录,分布式session 的功能。
-
通过Filter接口 session 和cookie 实现一个可以自动保存密码登录的效果