登录验证 springboot

先讲一下登录验证的过程:

1.客户端请求登录,输入必要的信息

2.服务器验证信息,通过后返回一个token 保存在cookie 中,并且把cookie 保存在redis里面,用来保存用户

3.每次请求页面,带上cookie,

4.客户端验证cookie,并且查验redis token 的正确性,如果正确,就是用户已登录的状态,可以返回请求的页面

实现过程:

登录-》验证-》生成token,返回cookie,保存cookie到redis-》每次验证cookie-》验证成功,返回页面

代码实现:

由于用到redis,需要添加maven依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

新建Controller 包含验证登录和注销登录两个方法:

@Controller
@RequestMapping("/seller")
@Slf4j
public class SellerLoginController {

    @Autowired
    private SellerService sellerService;
    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private ProjectUrlConfig projectUrlConfig;

    @RequestMapping("/login")
    public ModelAndView login(@RequestParam("openid") String openid,
                              HttpServletResponse response,
                              Map<String,Object> map)
    {
        //根据openid  查询是否存在
        SellerInfo sellerInfo = sellerService.findSellerInfo(openid);
        if(sellerInfo == null)
        {
           log.error("【微信扫码登录失败】用户未找到 ");
           throw new ResultException(ResultEnum.LOGIN_ERROR);

        }
        //找到后就保存到redis
        //生成token,有很多种方法,你可以根据根据实际情况选择,这里只是简单生成一个uuid
        String token = UUID.randomUUID().toString();
        //设置超时时间
        Integer expire = RedisContant.EXPIRE;

        redisTemplate.opsForValue().set(String.format(RedisContant.TOKEN_PREFIX, token), openid, expire, TimeUnit.SECONDS);

        //保存到cookies
        CookieUtil.set(response, CookieContant.TOKEN, token, expire);


        return new ModelAndView("redirect:"+projectUrlConfig.getSell()+"/sell/seller/order/list");

    }
    @GetMapping("/logout")
    public ModelAndView logout(HttpServletRequest request,
                               HttpServletResponse response,
                               Map<String ,Object> map)
    {
        //1.从cookie 里面查询 如果有
        Cookie cookie = CookieUtil.get(request,  CookieContant.TOKEN);
        if(cookie!=null)
        {
            //2.删除cookie数据
            CookieUtil.set(response, CookieContant.TOKEN, null, 0);
            //3.删除redis的数据
            redisTemplate.opsForValue().getOperations().delete(String.format(RedisContant.TOKEN_PREFIX, cookie.getValue()));

        }

        map.put("msg", ResultEnum.LOGOUT_SUCCESS);
        map.put("url", projectUrlConfig.getSell()+"/sell/seller/order/list");
        return new ModelAndView("common/success", map);


    }
}

在这里包含了保存cookie 和获取cookie 的两个方法,在CookieUtil类中

public class CookieUtil {
    /**
     * 设置
     * @param response
     * @param name
     * @param value
     * @param maxAge
     */
    public static void set(HttpServletResponse response,
                           String name,
                           String value,
                           int maxAge) {
        Cookie cookie = new Cookie(name, value);
        cookie.setPath("/");
        cookie.setMaxAge(maxAge);
        response.addCookie(cookie);
    }

    /**
     * 返回cookie
     * @param request
     * @param name
     * @return
     */
    public static Cookie get(HttpServletRequest request,

                           String name)
    {
        Map<String,Cookie> cookieMap = cookies2map(request);
        if(cookieMap!=null)
        {
            if(cookieMap.containsKey(name))
            {
                return cookieMap.get(name);
            }

        }
       return null;
    }

    /**
     * 将cookie 转换为 map
     * @param request
     * @return
     */
    private static Map<String,Cookie> cookies2map(HttpServletRequest request)
    {

        Map<String,Cookie> map  = new HashMap<>();
        Cookie[] cookies = request.getCookies();
        if (cookies!=null)
        {
            for(Cookie cookie:cookies)
            {
                map.put(cookie.getName(), cookie);
            }
        }
        return map;
    }
}

返回正确后,再每次请求的时候,我们都要验证一下cookie,我们可以把这个验证设置为一个切面,来进行验证

@Component
@Aspect
@Slf4j
public class SellAuthorizeAspect {

    @Autowired
    RedisTemplate redisTemplate;

    //进行验证的切面
    @Pointcut("execution(public * com.imooc.sell.controller.Seller*.*(..))")
    public void verify(){}


    @Before("verify()")
    public void doVerify()  {
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();

        HttpServletRequest request = servletRequestAttributes.getRequest();

        //查询cookie
        Cookie cookie = CookieUtil.get(request, CookieContant.TOKEN);
        if(cookie == null)
        {
            log.error("【登录验证】错误,没有登录");
            throw new SellAuthorizeException();
        }
        //查询radis
        if (!redisTemplate.opsForValue().getOperations().hasKey(String.format(RedisContant.TOKEN_PREFIX, cookie))) {
            log.error("【登录验证】错误,没有登录");
            throw new SellAuthorizeException();

        }

    }
}

在验证的时候,我们这里抛出了异常,说明是没有登录的异常,对于没有登录,我们会转到登录页面处理,这里就有一个异常的处理过程

先新建一个没有登录的异常

 

@Getter
@Setter
@ToString
public class SellAuthorizeException extends RuntimeException {

}

然后捕获异常进行处理 我们上面抛出的是SellAuthorizeException

@ControllerAdvice
public class SellAuthorizeExceptionHandle {
    @Autowired
    ProjectUrlConfig projectUrlConfig;

    @ExceptionHandler(value = SellAuthorizeException.class)
    public ModelAndView authorizeExceptionHandle()
    {

        return new ModelAndView("redirect:"http://localhost:8080"+
                "/sell/seller/login");
    }

}

这样一个登录的验证就做好了

发布了41 篇原创文章 · 获赞 4 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_37992974/article/details/89281657