链接: https://pan.baidu.com/s/1LkJDNwV5THPoywbEX6Gpyg
提取码: gajm
思路 : 这个我们需要两个接口来实现, 分别是发送验证码和登录功能
代码 :
- /**
- * 发送手机验证码
- */
- @PostMapping("code")
- public Result sendCode(@RequestParam("phone") String phone, HttpSession session) {
- // TODO 发送短信验证码并保存验证码
- return userService.sendCode(phone, session);
- }
-
- /**
- * 登录功能
- * @param loginForm 登录参数,包含手机号、验证码;或者手机号、密码
- */
- @PostMapping("/login")
- public Result login(@RequestBody LoginFormDTO loginForm, HttpSession session){
- // TODO 实现登录功能
- return userService.login(loginForm, session);
- }
思路 : 校验手机号(正则) ➡️ 生成验证码 ➡️ 将验证码保存到Session中 ➡️ 返回OK
代码 :
- @Override
- public Result sendCode(String phone, HttpSession session) {
- //1.校验(正则)手机号
- if (RegexUtils.isPhoneInvalid(phone)) {
- //2.如果不符合, 返回错误信息
- return Result.fail("手机号格式错误!");
- }
- //3.符合, 生成验证码
- String code = RandomUtil.randomNumbers(6);
- //4.保存验证码到session中
- session.setAttribute("code", code);
- //5.发送验证码 后期有空调阿里云的api
- log.debug("手机号:{} 发送短信验证码成功, 验证码: {}", phone, code);
- //6.返回OK
- return Result.ok();
- }
思路 : 校验手机号(正则) ➡️ 校验验证码 ➡️ 根据手机号查询用户 ➡️ 如果不存在就创建用户 ➡️ 保存用户信息到Session中
代码 :
- @Override
- public Result login(LoginFormDTO loginForm, HttpSession session) {
- //1.校验手机号
- String phone = loginForm.getPhone();
- if (RegexUtils.isPhoneInvalid(phone)) {
- //2.如果不符合, 返回错误信息
- return Result.fail("手机号格式错误!");
- }
- Enumeration
attributeNames = session.getAttributeNames(); - System.out.println(attributeNames);
- //3.校验验证码
- Object cacheCode = session.getAttribute("code");
- String code = loginForm.getCode();
- if (cacheCode == null || !cacheCode.toString().equals(code)){
- //4.不一致,报错
- return Result.fail("验证码错误");
- }
- //5.一致的话, 根据手机号查询用户
- User user = query().eq("phone", phone).one();
- //6.判断用户是否存在
- if (user == null) {
- //不存在, 创建新用户
- user = createUserWithPhone(phone);
- }
- //7.保存用户信息到session中
- session.setAttribute("user", user);
- return Result.ok();
- }
思路 : 利用SpringMVC的拦截器, 来拦截请求, 首先我们要制定拦截的规则, 最后再设置接口的拦截或放行
代码1 : 设置拦截规则
- public class LoginInterceptor implements HandlerInterceptor {
- @Override
- //前置拦截
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
-
- //1.获取session
- HttpSession session = request.getSession();
- //2.获取session中的用户
- Object user = session.getAttribute("user");
- //判断用户是否存在, 如果请求的接口没有被放行, 但是session中是存在用户信息, 该接口也可以被访问到
- if (user == null){
- //4.不存在, 拦截返回401状态码
- response.setStatus(401);
- return false;
- }
- //存在,保存用户信息到ThreadLocal
- UserHolder.saveUser((User)user);
- //6.放行
- return true;
- }
-
- @Override
- //Controller执行之后拦截
- public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
- HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
- }
-
- @Override
- //视图渲染之后
- public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
- //移除用户
- UserHolder.removeUser();
- }
- }
代码2 : 设置要放行的接口
- @Configuration
- public class MvcConfig implements WebMvcConfigurer {
-
- @Override
- public void addInterceptors(InterceptorRegistry registry) {
- registry.addInterceptor(new LoginInterceptor())
- //要方行的接口,
- .excludePathPatterns(
- "/user/code",
- "/user/login"
- );
- }
- }
session共享问题:多台Tomcat并不共享session存储空间,当请求切换到不同tomcat服务时导致数据丢失的问题。 session的替代方案应该满足:
数据共享
内存存储 key、
value结构
