一、注册时生成Token
1.用户注册时生成Token,存入redis。
@ApiOperation(value = "用户注册", notes = "用户注册", httpMethod = "POST")
@PostMapping("/regist")
public IMOOCJSONResult regist(@RequestBody UserBO userBO,
HttpServletRequest request,
HttpServletResponse response) {
String username = userBO.getUsername();
String password = userBO.getPassword();
String confirmPwd = userBO.getConfirmPassword();
// 0. 判断用户名和密码必须不为空
if (StringUtils.isBlank(username) ||
StringUtils.isBlank(password) ||
StringUtils.isBlank(confirmPwd)) {
return IMOOCJSONResult.errorMsg("用户名或密码不能为空");
}
// 1. 查询用户名是否存在
boolean isExist = userService.queryUsernameIsExist(username);
if (isExist) {
return IMOOCJSONResult.errorMsg("用户名已经存在");
}
// 2. 密码长度不能少于6位
if (password.length() < 6) {
return IMOOCJSONResult.errorMsg("密码长度不能少于6");
}
// 3. 判断两次密码是否一致
if (!password.equals(confirmPwd)) {
return IMOOCJSONResult.errorMsg("两次密码输入不一致");
}
// 4. 实现注册
Users userResult = userService.createUser(userBO);
// 实现用户的redis会话
UsersVO usersVO = conventUsersVO(userResult);
//存入Cookie然后前端获取,CookieUtils为自定义的工具类
CookieUtils.setCookie(request, response, "user",
JsonUtils.objectToJson(usersVO), true);
return IMOOCJSONResult.ok();
}
2.conventUsersVO方法
public UsersVO conventUsersVO(Users user) {
// 实现用户的redis会话
String uniqueToken = UUID.randomUUID().toString().trim();
redisOperator.set(REDIS_USER_TOKEN + ":" + user.getId(), uniqueToken);//redisOperator为定定义的工具类,具体请看我主页Redis实现缓存这篇文章
UsersVO usersVO = new UsersVO();//封装的用户基本信息
//user为注册用户时生成的用户对象,然后复制给你usrsVO,目的是去掉没有用的信息
BeanUtils.copyProperties(user, usersVO);
//赋值
usersVO.setUserUniqueToken(uniqueToken);
return usersVO;
}
3.CookieUtils类
public final class CookieUtils {
final static Logger logger = LoggerFactory.getLogger(CookieUtils.class);
/**
*
* @Description: 得到Cookie的值, 不编码
* @param request
* @param cookieName
* @return
*/
public static String getCookieValue(HttpServletRequest request, String cookieName) {
return getCookieValue(request, cookieName, false);
}
/**
*
* @Description: 得到Cookie的值
* @param request
* @param cookieName
* @param isDecoder
* @return
*/
public static String getCookieValue(HttpServletRequest request, String cookieName, boolean isDecoder) {
Cookie[] cookieList = request.getCookies();
if (cookieList == null || cookieName == null) {
return null;
}
String retValue = null;
try {
for (int i = 0; i < cookieList.length; i++) {
if (cookieList[i].getName().equals(cookieName)) {
if (isDecoder) {
retValue = URLDecoder.decode(cookieList[i].getValue(), "UTF-8");
} else {
retValue = cookieList[i].getValue();
}
break;
}
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return retValue;
}
/**
*
* @Description: 得到Cookie的值
* @param request
* @param cookieName
* @param encodeString
* @return
*/
public static String getCookieValue(HttpServletRequest request, String cookieName, String encodeString) {
Cookie[] cookieList = request.getCookies();
if (cookieList == null || cookieName == null) {
return null;
}
String retValue = null;
try {
for (int i = 0; i < cookieList.length; i++) {
if (cookieList[i].getName().equals(cookieName)) {
retValue = URLDecoder.decode(cookieList[i].getValue(), encodeString);
break;
}
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return retValue;
}
/**
*
* @Description: 设置Cookie的值 不设置生效时间默认浏览器关闭即失效,也不编码
* @param request
* @param response
* @param cookieName
* @param cookieValue
*/
public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName,
String cookieValue) {
setCookie(request, response, cookieName, cookieValue, -1);
}
/**
*
* @Description: 设置Cookie的值 在指定时间内生效,但不编码
* @param request
* @param response
* @param cookieName
* @param cookieValue
* @param cookieMaxage
*/
public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName,
String cookieValue, int cookieMaxage) {
setCookie(request, response, cookieName, cookieValue, cookieMaxage, false);
}
/**
*
* @Description: 设置Cookie的值 不设置生效时间,但编码
* 在服务器被创建,返回给客户端,并且保存客户端
* 如果设置了SETMAXAGE(int seconds),会把cookie保存在客户端的硬盘中
* 如果没有设置,会默认把cookie保存在浏览器的内存中
* 一旦设置setPath():只能通过设置的路径才能获取到当前的cookie信息
* @param request
* @param response
* @param cookieName
* @param cookieValue
* @param isEncode
*/
public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName,
String cookieValue, boolean isEncode) {
setCookie(request, response, cookieName, cookieValue, -1, isEncode);
}
/**
*
* @Description: 设置Cookie的值 在指定时间内生效, 编码参数
* @param request
* @param response
* @param cookieName
* @param cookieValue
* @param cookieMaxage
* @param isEncode
*/
public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName,
String cookieValue, int cookieMaxage, boolean isEncode) {
doSetCookie(request, response, cookieName, cookieValue, cookieMaxage, isEncode);
}
/**
*
* @Description: 设置Cookie的值 在指定时间内生效, 编码参数(指定编码)
* @param request
* @param response
* @param cookieName
* @param cookieValue
* @param cookieMaxage
* @param encodeString
*/
public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName,
String cookieValue, int cookieMaxage, String encodeString) {
doSetCookie(request, response, cookieName, cookieValue, cookieMaxage, encodeString);
}
/**
*
* @Description: 删除Cookie带cookie域名
* @param request
* @param response
* @param cookieName
*/
public static void deleteCookie(HttpServletRequest request, HttpServletResponse response,
String cookieName) {
doSetCookie(request, response, cookieName, null, -1, false);
// doSetCookie(request, response, cookieName, "", -1, false);
}
/**
*
* @Description: 设置Cookie的值,并使其在指定时间内生效
* @param request
* @param response
* @param cookieName
* @param cookieValue
* @param cookieMaxage cookie生效的最大秒数
* @param isEncode
*/
private static final void doSetCookie(HttpServletRequest request, HttpServletResponse response,
String cookieName, String cookieValue, int cookieMaxage, boolean isEncode) {
try {
if (cookieValue == null) {
cookieValue = "";
} else if (isEncode) {
cookieValue = URLEncoder.encode(cookieValue, "utf-8");
}
Cookie cookie = new Cookie(cookieName, cookieValue);
if (cookieMaxage > 0)
cookie.setMaxAge(cookieMaxage);
if (null != request) {// 设置域名的cookie
String domainName = getDomainName(request);
logger.info("========== domainName: {} ==========", domainName);
if (!"localhost".equals(domainName)) {
cookie.setDomain(domainName);
}
}
cookie.setPath("/");
response.addCookie(cookie);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
*
* @Description: 设置Cookie的值,并使其在指定时间内生效
* @param request
* @param response
* @param cookieName
* @param cookieValue
* @param cookieMaxage cookie生效的最大秒数
* @param encodeString
*/
private static final void doSetCookie(HttpServletRequest request, HttpServletResponse response,
String cookieName, String cookieValue, int cookieMaxage, String encodeString) {
try {
if (cookieValue == null) {
cookieValue = "";
} else {
cookieValue = URLEncoder.encode(cookieValue, encodeString);
}
Cookie cookie = new Cookie(cookieName, cookieValue);
if (cookieMaxage > 0)
cookie.setMaxAge(cookieMaxage);
if (null != request) {// 设置域名的cookie
String domainName = getDomainName(request);
logger.info("========== domainName: {} ==========", domainName);
if (!"localhost".equals(domainName)) {
cookie.setDomain(domainName);
}
}
cookie.setPath("/");
response.addCookie(cookie);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
*
* @Description: 得到cookie的域名
* @return
*/
private static final String getDomainName(HttpServletRequest request) {
String domainName = null;
String serverName = request.getRequestURL().toString();
if (serverName == null || serverName.equals("")) {
domainName = "";
} else {
serverName = serverName.toLowerCase();
serverName = serverName.substring(7);
final int end = serverName.indexOf("/");
serverName = serverName.substring(0, end);
if (serverName.indexOf(":") > 0) {
String[] ary = serverName.split("\\:");
serverName = ary[0];
}
final String[] domains = serverName.split("\\.");
int len = domains.length;
if (len > 3 && !isIp(serverName)) {
// www.xxx.com.cn
domainName = "." + domains[len - 3] + "." + domains[len - 2] + "." + domains[len - 1];
} else if (len <= 3 && len > 1) {
// xxx.com or xxx.cn
domainName = "." + domains[len - 2] + "." + domains[len - 1];
} else {
domainName = serverName;
}
}
return domainName;
}
public static String trimSpaces(String IP){//去掉IP字符串前后所有的空格
while(IP.startsWith(" ")){
IP= IP.substring(1,IP.length()).trim();
}
while(IP.endsWith(" ")){
IP= IP.substring(0,IP.length()-1).trim();
}
return IP;
}
public static boolean isIp(String IP){//判断是否是一个IP
boolean b = false;
IP = trimSpaces(IP);
if(IP.matches("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}")){
String s[] = IP.split("\\.");
if(Integer.parseInt(s[0])<255)
if(Integer.parseInt(s[1])<255)
if(Integer.parseInt(s[2])<255)
if(Integer.parseInt(s[3])<255)
b = true;
}
return b;
}
}
二、分布式会话拦截器,Token实现请求拦截
1.定义一个拦截器的类
public class UserTokenInterceptor implements HandlerInterceptor {
@Autowired
private RedisOperator redisOperator; //该类为封装的redis工具类,redis实现缓存功能这节可见
public static final String REDIS_USER_TOKEN = "redis_user_token";
/**
* 拦截请求,在访问controller调用之前
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// System.out.println("进入到拦截器,被拦截。。。");
String userId = request.getHeader("headerUserId");
String userToken = request.getHeader("headerUserToken");
if (StringUtils.isNotBlank(userId) && StringUtils.isNotBlank(userToken)) {
String uniqueToken = redisOperator.get(REDIS_USER_TOKEN + ":" + userId);
if (StringUtils.isBlank(uniqueToken)) {
// System.out.println("请登录...");
returnErrorResponse(response, IMOOCJSONResult.errorMsg("请登录..."));
return false;
} else {
if (!uniqueToken.equals(userToken)) {
// System.out.println("账号在异地登录...");
returnErrorResponse(response, IMOOCJSONResult.errorMsg("账号在异地登录..."));
return false;
}
}
} else {
// System.out.println("请登录...");
returnErrorResponse(response, IMOOCJSONResult.errorMsg("请登录..."));
return false;
}
/**
* false: 请求被拦截,被驳回,验证出现问题
* true: 请求在经过验证校验以后,是OK的,是可以放行的
*/
return true;
}
public void returnErrorResponse(HttpServletResponse response,
IMOOCJSONResult result) {
OutputStream out = null;
try {
response.setCharacterEncoding("utf-8");
response.setContentType("text/json");
out = response.getOutputStream();
out.write(JsonUtils.objectToJson(result).getBytes("utf-8"));
out.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 请求访问controller之后,渲染视图之前
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
/**
* 请求访问controller之后,渲染视图之后
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
2.注册拦截器,我这是SpringBoot工程
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Bean
public UserTokenInterceptor userTokenInterceptor() {
return new UserTokenInterceptor();
}
/**
* 注册拦截器
* @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(userTokenInterceptor())
.addPathPatterns("/hello")
.addPathPatterns("/shopcart/add")
.addPathPatterns("/shopcart/del")
.addPathPatterns("/address/list")
.addPathPatterns("/address/add")
.addPathPatterns("/address/update")
.addPathPatterns("/address/setDefalut")
.addPathPatterns("/address/delete")
.addPathPatterns("/orders/*")
.addPathPatterns("/center/*")
.addPathPatterns("/userInfo/*")
.addPathPatterns("/myorders/*")
.addPathPatterns("/mycomments/*")
.excludePathPatterns("/myorders/deliver")
.excludePathPatterns("/orders/notifyMerchantOrderPaid");
WebMvcConfigurer.super.addInterceptors(registry);
}
}