15.基于session实现登录& 前端项目部署

前端项目nginx部署

nginx配置文件


worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/json;

    sendfile        on;
    
    keepalive_timeout  65;

    server {
        listen       8080;
        server_name  localhost;
        # 指定前端项目所在的位置
        location / {
            root   html/hmdp;
            index  index.html index.htm;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }


        location /api {  
            default_type  application/json;
            #internal;  
            keepalive_timeout   30s;  
            keepalive_requests  1000;  
            #支持keep-alive  
            proxy_http_version 1.1;  
            rewrite /api(/.*) $1 break;  
            proxy_pass_request_headers on;
            #more_clear_input_headers Accept-Encoding;  
            proxy_next_upstream error timeout;  
            proxy_pass http://127.0.0.1:8081;
            #proxy_pass http://backend;
        }
    }

    upstream backend {
        server 127.0.0.1:8081 max_fails=5 fail_timeout=10s weight=1;
        #server 127.0.0.1:8082 max_fails=5 fail_timeout=10s weight=1;
    }  
}

启动nginx

在D:\centos7nginx\nginx-1.18.0\nginx-1.18.0目录下,执行start nginx.exe命令启动。

可以看出,地址http://localhost:8080/api请求  会转发到  http://localhost:8081上

例如:http://localhost:8080/api/shop-type/list   会转发到 http://localhost:8081/shop-type/list

正则表达式校验的工具类

package com.xkj.org.utils;

/**
 * @author 虎哥
 */
public abstract class RegexPatterns {
    /**
     * 手机号正则
     */
    public static final String PHONE_REGEX = "^1([38][0-9]|4[579]|5[0-3,5-9]|6[6]|7[0135678]|9[89])\\d{8}$";
    /**
     * 邮箱正则
     */
    public static final String EMAIL_REGEX = "^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$";
    /**
     * 密码正则。4~32位的字母、数字、下划线
     */
    public static final String PASSWORD_REGEX = "^\\w{4,32}$";
    /**
     * 验证码正则, 6位数字或字母
     */
    public static final String VERIFY_CODE_REGEX = "^[a-zA-Z\\d]{6}$";

}
package com.xkj.org.utils;

import cn.hutool.core.util.StrUtil;

/**
 * @author 虎哥
 */
public class RegexUtils {
    /**
     * 是否是无效手机格式
     * @param phone 要校验的手机号
     * @return true:符合,false:不符合
     */
    public static boolean isPhoneInvalid(String phone){
        return mismatch(phone, RegexPatterns.PHONE_REGEX);
    }
    /**
     * 是否是无效邮箱格式
     * @param email 要校验的邮箱
     * @return true:符合,false:不符合
     */
    public static boolean isEmailInvalid(String email){
        return mismatch(email, RegexPatterns.EMAIL_REGEX);
    }

    /**
     * 是否是无效验证码格式
     * @param code 要校验的验证码
     * @return true:符合,false:不符合
     */
    public static boolean isCodeInvalid(String code){
        return mismatch(code, RegexPatterns.VERIFY_CODE_REGEX);
    }

    // 校验是否不符合正则格式
    private static boolean mismatch(String str, String regex){
        if (StrUtil.isBlank(str)) {
            return true;
        }
        return !str.matches(regex);
    }
}

登录校验用户状态

因为很多功能都要校验用户,所以需要使用拦截器

拦截器校验了用户信息,将用户信息放入每一个线程的ThreadLocal中,每个线程需要用户信息就从自己的ThreadLocal中获取,保证的线程安全。

拦截器

package com.xkj.org.interceptor;

import com.xkj.org.entity.User;
import com.xkj.org.utils.UserHolder;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class LoginInterceptor implements HandlerInterceptor {


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        //1.获取session中的user
        User user = (User)request.getSession().getAttribute("user");
        //2.判断用户是否存在
        if (user == null) {
            //3.不存在,拦截, 401未授权
            response.setStatus(401);
            return false;
        }
        //4.存在,保存用户信息到ThreadLocal
        UserHolder.saveUser(user);
        //5.放行
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        //请求执行完毕,释放内存,threadlocal避免内存泄漏
        UserHolder.removeUser();
    }
}

 ThreadLocal

package com.xkj.org.utils;

import com.xkj.org.entity.User;

public class UserHolder {

    private static final ThreadLocal<User> t1 = new ThreadLocal<>();

    public static void saveUser(User user) {
        t1.set(user);
    }

    public static User getUser() {
        return t1.get();
    }

    public static void removeUser() {
        t1.remove();
    }
}

 配置拦截器

package com.xkj.org.config;

import com.xkj.org.interceptor.LoginInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class MvcConfig implements WebMvcConfigurer{

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //添加拦截器,排除一些不需要拦截的url
        registry.addInterceptor(new LoginInterceptor())
        .excludePathPatterns(
                "/user/code",
                "/user/login",
                "/blog/hot",
                "/shop/**",
                "/shop-type/**",
                "/upload/**",
                "voucher/**"

        );
    }
}

用户相关功能

发送验证码

登录用户

获取用户信息

package com.xkj.org.controller;

import com.xkj.org.dto.LoginFormDTO;
import com.xkj.org.dto.Result;
import com.xkj.org.entity.User;
import com.xkj.org.service.IUserService;
import com.xkj.org.utils.UserHolder;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;

@RequestMapping("/user")
@RestController
public class UserController {

    @Resource
    private IUserService userService;

    @PostMapping("/code")
    public Result sendCode(@RequestParam("phone") String phone, HttpSession session) {
        return userService.sendCode(phone, session);
    }


    @PostMapping("/login")
    public Result login(@RequestBody LoginFormDTO loginFormDTO, HttpSession session) {
        return userService.login(loginFormDTO, session);
    }


    @GetMapping("/me")
    public Result me() {
        User user = UserHolder.getUser();
        return Result.ok(user);

    }
}
package com.xkj.org.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xkj.org.dto.LoginFormDTO;
import com.xkj.org.dto.Result;
import com.xkj.org.entity.User;
import com.xkj.org.mapper.UserMapper;
import com.xkj.org.service.IUserService;
import com.xkj.org.utils.RegexUtils;
import com.xkj.org.utils.SystemConstants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpSession;

@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService{

    @Override
    public Result sendCode(String phone, HttpSession session) {
        //检验手机号
        if (RegexUtils.isPhoneInvalid(phone)) {
            return Result.fail("手机号无效");
        }
        //生成验证码
        String code = RandomUtil.randomString(6);
        //存入session
        session.setAttribute("code", code);
        //发送验证码给用户
        log.info("给用户发送验证码============={}", code);
        //返回
        return Result.ok("发送成功");
    }

    @Override
    public Result login(LoginFormDTO loginFormDTO, HttpSession session) {
        //校验手机号
        if (RegexUtils.isPhoneInvalid(loginFormDTO.getPhone())) {
            return Result.fail("手机号无效");
        }
        //校验验证码
        String cacheCode = session.getAttribute("code").toString();
        String code = session.getAttribute("code").toString();
        if (code == null || !code.equals(cacheCode)) {
            return Result.fail("验证码错误");
        }
        //根据手机号查询用户
        User user = query().eq("phone", loginFormDTO.getPhone()).one();
        if (user == null) {
            //用户不存在则创建用户
            user = createUser(loginFormDTO.getPhone());
        }
        //将用户放入session
        session.setAttribute("user", user);
        //返回
        return Result.ok();
    }

    private User createUser(String phone) {
        User user = new User();
        user.setPhone(phone);
        user.setNickName(SystemConstants.USER_NICK_NAME_PREFIX + RandomUtil.randomString(6));
        save(user);
        return user;
    }
}
  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

卷土重来…

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值