用cookie 和redis 实现登录,分布式session 的功能。

 @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);

    }

方法有业务无关的都可以审掉了。清晰。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值