1. 核心原理
主要是通过redis,当用户登录后生成一个随机的uuid作为token,将token作为键,user对象作为值存储到redis数据库中,同时将token保存到cookie中 ,当访问其他页面时判断cookie中是否有token,如果有,则根据此token从redis拿到用户信息即可。
关于springboot 操作redis方面请查看 : https://blog.youkuaiyun.com/junmoxi/article/details/80694405
2. User服务类
package com.pibigstar.springboot.service.impl;
import java.util.UUID;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.pibigstar.springboot.dao.JPADao;
import com.pibigstar.springboot.domain.User;
import com.pibigstar.springboot.service.RedisService;
import com.pibigstar.springboot.service.UserService;
@Service
public class UserServiceImpl implements UserService{
public static final String COOKIE_USER_TOKEN = "token";
public static final int COOKIE_TOKEN_TIMEOUT = 3600*24*2;//两天
@Autowired
private RedisService redisService;
/**
* 登录
* @param response
* @param loginVo
* @return
*/
@Override
public boolean login(HttpServletResponse response, LoginVo loginVo) {
if(loginVo == null) {
throw new GlobalException(CodeMsg.SERVER_ERROR);
}
String mobile = loginVo.getMobile();
String formPass = loginVo.getPassword();
//判断手机号是否存在
User user = getById(Long.parseLong(mobile));
if(user == null) {
throw new GlobalException(CodeMsg.MOBILE_NOT_EXIST);
}
//验证密码
String dbPass = user.getPassword();
String saltDB = user.getSalt();
String calcPass = MD5Util.formPassToDBPass(formPass, saltDB);
if(!calcPass.equals(dbPass)) {
throw new GlobalException(CodeMsg.PASSWORD_ERROR);
}
//生成cookie
String token = UUID.randomUUID().toString().replace("-", "");
addCookie(response, token, user);
return true;
}
/**
* 根据token从redis中拿到user对象
*/
@Override
public User getByToken(HttpServletResponse response, String token) {
if (token==null) {
return null;
}
User user = (User) redisService.getObject(token);
if (user!=null) {
//延长cookie有效期
addCookie(response,token,user);
}
return user;
}
/**
* 将token放到cookie中
* @param response
* @param token
* @param user
*/
private void addCookie(HttpServletResponse response, String token, User user) {
redisService.setObject(token, user,COOKIE_TOKEN_TIMEOUT);
Cookie cookie = new Cookie(COOKIE_USER_TOKEN, token);
//设置cookie有效期
cookie.setMaxAge(COOKIE_TOKEN_TIMEOUT);
cookie.setPath("/");
response.addCookie(cookie);
}
}
3. 读取cookie中的token
我们通过实现 HandlerMethodArgumentResolver 接口,重写里面的方法,将cookie中或者parameter中的token数据拿到然后查询出user注入到Controller中 的方法参数中
注册一个ArgumentResolvers
package com.pibigstar.springboot.config;
import java.util.List;
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;
@Configuration
public class WebConfig implements WebMvcConfigurer{
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(new UserArgumentResolver());
WebMvcConfigurer.super.addArgumentResolvers(resolvers);
}
具体实现类
package com.pibigstar.springboot.config;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Component;
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 org.thymeleaf.util.StringUtils;
import com.pibigstar.springboot.domain.User;
import com.pibigstar.springboot.service.UserService;
import com.pibigstar.springboot.service.impl.UserServiceImpl;
/**
* 拿到session或parameter中的token
* 通过token拿到redis中的user
* 将user注入到方法的参数中
* @author pibigstar
*
*/
@Component
public class UserArgumentResolver implements HandlerMethodArgumentResolver{
@Autowired
private UserService userService;
@Override
public boolean supportsParameter(MethodParameter parameter) {
Class<?> parameterType = parameter.getParameterType();
return parameterType==User.class;
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);
String cookieToken = getCookieToken(request,UserServiceImpl.COOKIE_USER_TOKEN);
String parameterToken = request.getParameter(UserServiceImpl.COOKIE_USER_TOKEN);
if (StringUtils.isEmpty(parameterToken) && StringUtils.isEmpty(cookieToken)) {
return null;
}
String token = StringUtils.isEmpty(parameterToken)?cookieToken:parameterToken;
return userService.getByToken(response,token);
}
private String getCookieToken(HttpServletRequest request,String cookieName) {
Cookie[] cookies = request.getCookies();
for (Cookie cookie : cookies) {
if (cookie.getName().equals(cookieName)) {
return cookie.getValue();
}
}
return null;
}
}
4. 使用
package com.pibigstar.springboot.web;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import com.pibigstar.springboot.domain.User;
@Controller
public class UserController {
/**
* 这里的user 是通过token从redis拿到的
* 具体实现在UserArgumentResolver中
*/
public String index(User user,Model model) {
if(user==null) {
return "login";
}else {
model.addAttribute("user",user);
return "index";
}
}
}
807

被折叠的 条评论
为什么被折叠?



