当前位置:网站首页>Redis implements SMS login function (I) traditional session login

Redis implements SMS login function (I) traditional session login

2022-06-30 04:33:00 Hongmeng oriented programming

be based on Session Implement the login process

Step by step to send SMS login  

(1) Send SMS verification code

(2) Login of SMS verification code

(3) Login verification

colony Session Sharing issues (Redis Login proposal )


be based on Session Implement the login process

Step by step to send SMS login  

(1) Send SMS verification code

UserController Control layer  

Control layer call service Layer interface  

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

IUserService Interface  

Interface definition sendCode() Method  

public interface IUserService extends IService<User> {

    Result sendCode(String phone, HttpSession session);
}

UserServiceImpl Implementation interface method  

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

    @Override
    public Result sendCode(String phone, HttpSession session) {
        //1.  Check cell phone number 
        if (RegexUtils.isPhoneInvalid(phone)) {
            //2. If it doesn't meet , Return error message 
            return Result.fail(" Mobile number format error ");
        }

        //3.  accord with , Generate verification code 
        String code = RandomUtil.randomNumbers(6);

        //4.  Save the verification code to session
        session.setAttribute("code",code);

        //5.  Send verification code 
        log.debug(" SMS verification code sent successfully , Verification Code :{}",code);

        // return ok
        return Result.ok();
    }
}

Be careful :

Many tool classes are used in the above code , The definitions of each tool class are as follows :

RegexUtils ( Check cell phone number )

public class RegexUtils {
    /**
     *  Whether it is an invalid mobile phone format 
     * @param phone  Mobile number to be verified 
     * @return true: accord with ,false: Do not conform to the 
     */
    public static boolean isPhoneInvalid(String phone){
        return mismatch(phone, RegexPatterns.PHONE_REGEX);
    }
}

RegexUtils Called in  RegexPatterns( Regular check ) 

public abstract class RegexPatterns {
    /**
     *  Cell phone number is regular 
     */
    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}$";
}

We restart the service , Enter the phone number on the front page , Click to get the verification code , stay idea Log in :

It indicates that the function has been completed !

(2) Login of SMS verification code

UserController Control layer   

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

IUserService Interface  

Interface definition login() Method  

public interface IUserService extends IService<User> {

    Result login(LoginFormDTO loginForm, HttpSession session);
}

UserServiceImpl Implementation interface method   

@Override
public Result login(LoginFormDTO loginForm, HttpSession session) {

    //1.  Check cell phone number 
    String phone = loginForm.getPhone();
    if (RegexUtils.isPhoneInvalid(phone)) {
        return Result.fail(" Mobile number format error ");
    }

    //2.  Verification code 
    Object cacheCode = session.getAttribute("code");
    String code = loginForm.getCode();
    if (cacheCode == null || !cacheCode.toString().equals(code)){
        //3.  atypism , Report errors 
        return Result.fail(" Verification code error ");
    }

    //4. Agreement , Query the user according to the mobile phone number 
    User user = query().eq("phone", phone).one();

    //5.  Judge whether the user exists 
    if (user == null){
        //6.  non-existent , Create a new user 
        user = createUserWithPhone(phone);
    }

    //7. Save user information to session
    session.setAttribute("user",BeanUtil.copyProperties(user,UserDTO.class));
    return Result.ok();
}

stay login() Call in method createUserWithPhone() Method to create a user  

private User createUserWithPhone(String phone) {

    // 1. Create user 
    User user = new User();
    user.setPhone(phone);
    user.setNickName(USER_NICK_NAME_PREFIX + RandomUtil.randomString(10));

    // 2. Save the user 
    save(user);
    return user;
}

(3) Login verification

Interceptor  LoginInterceptor 

Interceptors are used here Verify that the user exists , Log in when you exist ; conversely return false 

public class LoginInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //1.  obtain session
        HttpSession session = request.getSession();
        //2. obtain session Users in 
        Object user = session.getAttribute("user");
        //3.  Judge whether the user exists 
        if (user == null){
            //4.  non-existent , Intercept 
            response.setStatus(401);
            return false;
        }

        //5.  There is   Save user information to ThreadLocal
        UserHolder.saveUser((UserDTO) user);
        //6.  release 
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // Remove users 
        UserHolder.removeUser();
    }
}

Configure interceptors MvcConfig

Make the interceptor LoginInterceptor  take effect ! And define the intercepted object .

stay SpringBoot Can be used in addPathPatterns Configure the path to be intercepted 、excludePathPatterns Configure the path that should not be blocked .

here , Express Released resources ( That is, no login is required , You can access the page )

@Configuration
public class MvcConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //  Login interceptor 
        registry.addInterceptor(new LoginInterceptor())
                .excludePathPatterns(
                        "/shop/**",
                        "/voucher/**",
                        "/shop-type/**",
                        "/upload/**",
                        "/blog/hot",
                        "/user/code",
                        "/user/login"
                );
    }
}

Be careful :

The above series of codes , We also made security considerations , We used UserDTO, It's not used directly User, This reduces the cost of data transmission , Second, to avoid User Sensitive data disclosure in !

UserDTO

@Data
public class UserDTO {
    private Long id;
    private String nickName;
    private String icon;
}

colony Session Sharing issues (Redis Login proposal )

Let's take a look at this picture , When the program reaches the performance bottleneck , We need to replace the original one Tomcat, Expand Tomcat colony , But each one Tomcat There will be one of their own Session Space Different Tomcat Of Session It's independent of each other ). If we do not adjust the login, the login will fail .

In the early Tomcat Yes, I did Session Copy ! But such a scheme would lead to Memory waste ; During the copy process Generate delay , If in this delay Inside There will also be problems if someone visits !

So we urgently need one that can replace Session Things that are , This item needs to meet :

  • Data sharing
  • Memory storage
  • key、value structure

Obviously with Redis To achieve SMS login function Have a natural advantage .

 

原网站

版权声明
本文为[Hongmeng oriented programming]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/181/202206300430171713.html