那个做图网站叫什么,Wordpress图床对接阿里云,wordpress主题目录,自学网站建设目录
基于Session
Controller层
Service层
ServiceImpl层
编辑校验登录状态
ThreadLocal
登录拦截器
添加拦截器到Config
Controller层实现
基于Redis
ServiceImpl
新增刷新拦截器
添加拦截器到Config 基于Session Controller层 /*** 发送手机验证码*/PostMappi…目录
基于Session
Controller层
Service层
ServiceImpl层
编辑校验登录状态
ThreadLocal
登录拦截器
添加拦截器到Config
Controller层实现
基于Redis
ServiceImpl
新增刷新拦截器
添加拦截器到Config 基于Session Controller层 /*** 发送手机验证码*/PostMapping(code)public Result sendCode(RequestParam(phone) String phone, HttpSession session) {// TODO 发送短信验证码并保存验证码return userService.sendCode(phone,session);}/*** 登录功能,不存在用户则自动创建用户* param loginForm 登录参数包含手机号、验证码或者手机号、密码* RequestBody注解用于把前端的json数据转换成DTO对象*/PostMapping(/login)public Result login(RequestBody LoginFormDTO loginForm, HttpSession session){//将请求体中的数据转换为特定的对象或数据类型绑定到方法的参数上// TODO 实现登录功能return userService.login(loginForm,session);}
Service层 Result sendCode(String phone, HttpSession session);Result login(LoginFormDTO loginForm, HttpSession session);
ServiceImpl层 //登录Overridepublic Result login(LoginFormDTO loginForm, HttpSession session) {//发送验证码和登录是两次不同的请求要对手机号做二次校验//1.再次获取手机号并再次校验手机号String phone loginForm.getPhone();if(RegexUtils.isPhoneInvalid(phone)){//2.不符合返回错误信息return Result.fail(手机号格式错误);}//3.手机号校验成功校验验证码验证码从session获取String code session.getAttribute(code);//发送的验证码String logincode loginForm.getCode();//用户填写的验证码if (codenull||!code.toString().equals(logincode)){//4.验证码错误返回信息return Result.fail(验证码错误);}//5.验证码一致查询是否存在用户//query()是Mybatis-Plus提供的本类继承了extends ServiceImplUserMapper, UserUser user query().eq(phone, phone).one();if (usernull){//6.用户不存在则创建新用户新用户信息要保存到session所以这里把新建的user返回usercreateUserWithPhone(phone);}// 7.保存用户信息到session//user信息过多不易直接保存到session会加大内存负载此处转化成userDTO,还可以隐藏用户敏感信息UserDTO userDTO BeanUtil.copyProperties(user, UserDTO.class);session.setAttribute(user,userDTO);//访问tomcat时。sessionID自动写到了cookie中作为以后的登录凭证return Result.ok();}//自动注册用户private User createUserWithPhone(String phone) {User usernew User();user.setPhone(phone);//生成随机用户名user.setNickName(user_RandomUtil.randomString(5));save(user);//保存用户到数据库,mybatis-plus提供的return user;}//发送验证码Overridepublic Result sendCode(String phone, HttpSession session) {//1. 校验手机号if(RegexUtils.isPhoneInvalid(phone)){//2. 不符合返回错误信息return Result.fail(手机号格式错误);}//3.符合生成6位验证码String code RandomUtil.randomNumbers(6);//4.验证码保存到session稍后返回给服务端以便服务端进行登录验证session.setAttribute(code,code);//5.发送验证码这里验证码输出到控制台log.info(验证码发送成功{},code);//6.返回return Result.ok();}
校验登录状态
上面完成了短信验证码的发送及登录注册用户如果登陆成功就要进入个人主页但是进入个人主页需要验证用户的登录状态接下来使用拦截器和ThreadLocal完成登录状态校验 ThreadLocal
public class UserHolder {private static final ThreadLocalUserDTO tl new ThreadLocal();public static void saveUser(UserDTO user){tl.set(user);}public static UserDTO getUser(){return tl.get();}public static void removeUser(){tl.remove();}
}
登录拦截器
//这是一个自定义的拦截器类用于校验登陆状态
//需要在config中添加到拦截器中才会生效
public class LoginInterceptor implements HandlerInterceptor {Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {UserHolder.removerUser();}Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//1.获取sessionHttpSession sessionrequest.getSession();//2.获取session中的用户Object usersession.getAttribute(user);//3.判断用户是否存在if(usernull){//4.不存在拦截response.setStatus(401);return false; }//5.存在保存到ThreadLocal并放行UserHolder.saveUSer(user);return true;}
}添加拦截器到Config
Configuration
public class MvcConfig implements WebMvcConfigurer {Overridepublic void addInterceptors(InterceptorRegistry registry) {// 登录拦截器registry.addInterceptor(new LoginInterceptor()).excludePathPatterns(/shop/**,/voucher/**,/shop-type/**,/upload/**,/blog/hot,/user/code,/user/login);}
}
Controller层实现
//登录校验状态GetMapping(/me)//个人主页public Result me(){// TODO 获取当前登录的用户并返回//在拦截器LoginInterceptor中已经把用户保存到localthreadUserDTO user UserHolder.getUser();return Result.ok(user);}
基于Redis 接下来在上面代码的基础上修改serviceImpl和拦截器及config
ServiceImpl //注入stringRedisTemplateResourceprivate StringRedisTemplate stringRedisTemplate;Overridepublic Result login(LoginFormDTO loginForm, HttpSession session) {//1.校验手机号String phone loginForm.getPhone();if(RegexUtils.isPhoneInvalid(phone)){//2.不符合返回错误信息return Result.fail(手机号格式错误);}//3.手机号校验成功校验验证码验证码从redis中获取String code stringRedisTemplate.opsForValue().get(login:code:phone);String logincode loginForm.getCode();if (codenull||!code.toString().equals(logincode)){//4.验证码错误return Result.fail(验证码错误);}//5.验证码一致查询是否存在用户//query()是mp提供的本类继承了extends ServiceImplUserMapper, UserUser user query().eq(phone, phone).one();if (usernull){//6.不存在用户创建新用户usercreateUserWithPhone(phone);}//7.用户存在生成用户的token作为登录凭证String token UUID.randomUUID().toString(true);//8.存入redis时用的hash存储因此这里要把userDto转换成hashmapUserDTO userDTO BeanUtil.copyProperties(user, UserDTO.class);MapString, Object userMap BeanUtil.beanToMap(userDTO,new HashMap(), CopyOptions.create().setIgnoreNullValue(true).setFieldValueEditor((fieldName,fieldValue)-fieldValue.toString()));//9.token存入redis并设置token有效期stringRedisTemplate.opsForHash().putAll(login:token:token,userMap); stringRedisTemplate.expire(login:token:,30,TimeUnit.MINUTES);return Result.ok(token);} Overridepublic Result sendCode(String phone, HttpSession session) {//1.校验手机号if(RegexUtils.isPhoneInvalid(phone)){//2.不符合返回错误信息return Result.fail(手机号格式错误);}//2.符合生成验证码String code RandomUtil.randomNumbers(6);//3.保存到redis中,设置有效期1分钟stringRedisTemplate.opsForValue().set(login:code:phone,code,1L, TimeUnit.MINUTES);//4.发送验证码给客户log.info(验证码发送成功{},code);//返回return Result.ok();}
新增刷新拦截器
用于刷新Token有效期这里做了拦截器的优化。在第一个拦截器会获取token根据token去redis查询用户如果查到就说明用户已经登陆过了此时只需要刷新token有效期并保存到threadlocal然后放行。如果没有查到说明是未登录用户或者登录已经过期那么token也是null的也直接放行所以第一个拦截器虽然拦截一切路径但不论如何最后都会放行其主要作用是对已登录用户刷新token在第二个拦截器才会对未登录用户进行限制决定放不放行。 public class RefreshTokenInterceptor implements HandlerInterceptor {private StringRedisTemplate stringRedisTemplate;public RefreshTokenInterceptor(StringRedisTemplate stringRedisTemplate) {this.stringRedisTemplate stringRedisTemplate;}Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 1.获取请求头中的tokenString token request.getHeader(authorization);if (StrUtil.isBlank(token)) {return true;}// 2.基于TOKEN获取redis中的用户String key login:token token;MapObject, Object userMap stringRedisTemplate.opsForHash().entries(key);// 3.判断用户是否存在if (userMap.isEmpty()) {return true;}// 5.将查询到的hash数据转为UserDTOUserDTO user BeanUtil.fillBeanWithMap(userMap, new UserDTO(), false);// 6.存在保存用户信息到 ThreadLocalUserHolder.saveUser(user);// 7.刷新token有效期stringRedisTemplate.expire(key, 30L, TimeUnit.MINUTES);// 8.放行return true;}Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {// 移除用户UserHolder.removeUser();}
}添加拦截器到Config
Configuration
public class MvcConfig implements WebMvcConfigurer {Resourceprivate StringRedisTemplate stringRedisTemplate;Overridepublic void addInterceptors(InterceptorRegistry registry) {// 登录拦截器registry.addInterceptor(new LoginInterceptor()).excludePathPatterns(/shop/**,/voucher/**,/shop-type/**,/upload/**,/blog/hot,/user/code,/user/login).order(1);//设置拦截器的优先级// token刷新的拦截器拦截所有请求registry.addInterceptor(new RefreshTokenInterceptor(stringRedisTemplate)).addPathPatterns(/**).order(0);//后注册的拦截器先执行}
}