@[TOC]

preface

Yesterday took time to finally put up the back end, ready to write the back end, as a result of the first time to do before and after the end of the separation, I made a lot of fool, check the data for a long time found that a small detail did not do well, angry me.

registered

Since want to log in that must be first not register, register to log in after ah. So this is after all as a front and back end separation of the project, so the logic of the registration part is also divided into two parts, one is the front-end part, one is the back-end part.

Front-end partial logic

There are really only two front ends.

About this part, the front end generates the verification code itself, and the front end verifies whether the account password length is legal.See the front-end code for this part:Vue actual combat development (a) verification code and login page

Send the request

This is also the important part, I’m using Axios to send the request. But there’s one detail that’s important hereThe request parameters sent by Axios are wrapped in the requestBody, which is related to how we get the data later. I didn’t know this before, so I couldn’t receive the parametersBut there’s one thing we have to do first, and that’sCross domain processingI did this in the front end, not the back end, in order to ensure the safety of my back end.

proxyTable: {

      '/boot': {
        target: 'http://localhost:8000/'.changeOrigin: true.pathRewrite: {
          '^/boot': ' '}}},Copy the code

Target is your server, and /boot is the host.So now let’s start sending requests

    Register(){
      this.axios({
        url: "/boot/regist".method: 'post'.data: {
          username:  this.formRegist.username,
          password: this.formRegist.password.toLowerCase(),
        }
      }).then(res= >{
        this.flag = res.data.flag;
        if(this.flag =='1'){
          alert("Registration successful")
          this.$router.push("/login")}else {
          alert("Failed registration user name already exists!")}})Copy the code

The back-end processing

So I’m going to talk about that parameter here, and that flag is the parameter that indicates whether the user is successfully registered, and that flag is 1 if the user is successfully registered and 0 if the user is successfully registered

Now the logic behind springBoot is simple: check if the user name exists, unregister if it does, and return a flag

@Controller
public class UserRegist {
    @Autowired
    UserService userService;
    @Autowired
    RegistMessage registMessage;
    @ResponseBody
    @PostMapping("/regist")
    public RegistMessage SaveUser(@RequestBody Map<String, Object> usermap){
        String username = (String) usermap.get("username");
        String password = (String) usermap.get("password");

        QueryWrapper<User> UsersWrapper = new QueryWrapper<>();
        UsersWrapper.eq("UserName",username);
        if(userService.IsExitsUser(UsersWrapper)){
            registMessage.setFlag(0);
            return registMessage;
        }
        else {
            User user = new User();
            user.setUserName(username);
            user.setUserPassword(password);
            userService.SaveUser(user);
            registMessage.setFlag(1);
            returnregistMessage; }}}Copy the code

Then you can see the registered account password in the database.

And then the front end gets the data backJudge the situation.

The login

We also need to generate a token to record the login status of the user, and since it is separated from the front and back end, we can’t use session or cookie directly, as we did with Django. Request. Session Or direct Httpsession like SpringBoot. Here we need to encrypt the token ourselves and let the front-end save the token.

So let’s look at the front first. All the front-end has to do is send the user and password, and then receive the token. Token will be brought in for future requests for sensitive pages.

Front-end Token Acquisition

That’s all there is to it

 logincount(){
      this.axios({
        url: "/boot/login".method: 'post'.headers: { "Huterox": "hello" },
        data: {
          username:  this.formLogin.username,
          password: this.formLogin.password.toLowerCase(),
        }
      }).then(res= >{
        this.formLogin.success = res.data.success
        this.formLogin.token = res.data.token
        if(this.formLogin.success =='1') {// Set the token to expire within seven days
          localStorage.setExpire("token".this.formLogin.token,1000*60*60*24*7);
          alert("Login successful ~")
          this.$router.push("/space")}else {
          alert("Wrong username or password!")}})},Copy the code

That success and flag are the same thing.

Front-end Token status management

Since there is no cookie, we need to save the token by ourselves. However, the session of Vuex will be gone after the page is closed or refreshed, so we can only use localStorage. However, there is no way to set the expiration time of vuex, so we need to deal with it by ourselves. Method of encapsulating localStorage.

Storage.prototype.setExpire=(key, value, expire) = >{
  let obj={
    data:value,
    time:Date.now(),
    expire:expire
  };
  localStorage.setItem(key,JSON.stringify(obj));
}

Storage.prototype.getExpire= key= >{
  let val =localStorage.getItem(key);
  if(! val){return val;
  }
  val =JSON.parse(val);
  if(Date.now()-val.time>val.expire){
    localStorage.removeItem(key);
    return null;
  }
  return val.data;
}


Copy the code

After the sensitive page in the judgment of whether token is good.

localStorage.getExpire("token")

The back-end processing

This is relatively easy on the front end, so the back end is next. Of course, the back end mainly involves generating and validating tokens. After all, the front end only needs to judge the wrong token, and the back end needs to verify. As for the fear of malicious tampering, as long as you change the token, I will fail the back end verification. I will introduce Redis to record this situation. If you can’t get past that there’s a good chance it’s been maliciously tampered with, you put it on the watch list, go over the limit and put it in a dark room, or call the browser to locate it. I pay more attention to the safety of this piece, compared to play for a period of time.

So let’s go back here and talk about what we’re going to do.

The user login

Then the front view returns the result. Success is token

To generate the token

JWT is used here

        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.6.0</version>
        </dependency>
Copy the code

package com.huterox.whiteholeboot.utils.TokenProccessor;


/** * Generate token */

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import com.huterox.whiteholeboot.Dao.Mapper.UserMapper.UserServer.UserService;
import com.huterox.whiteholeboot.Dao.Pojo.UserPojo.User;
import io.jsonwebtoken.*;
import org.springframework.beans.factory.annotation.Autowired;

public class TokenProccessor {


    private static UserService userService=new UserService();
    private static final long EXPIRE_TIME=60*60*1000*24*7; // The expiration time is 7 days
    private static final String KEY = "huterox"; // Encrypt the key

    /** * Generate token * Because the token will be generated only when the account password is correct, only the user name is needed to identify *@paramUserName userName *@return* /
    public static String createToken(String userName){
        Map<String,Object> header = new HashMap();
        header.put("typ"."JWT");
        header.put("alg"."HS256");
        JwtBuilder builder = Jwts.builder().setHeader(header)
                .setExpiration(new Date(System.currentTimeMillis()+EXPIRE_TIME))
                .setSubject(userName)// Set the information, that is, the username
                .setIssuedAt(new Date())
                .signWith(SignatureAlgorithm.HS256,KEY);// Encryption mode
        return builder.compact();
    }

    /** * Verify the token is valid *@paramToken Token * carried in the request header@returnToken verification result 2- Token expires. 1- Token authentication succeeds. 0- Token authentication fails */
    public static int verify(String token){
        Claims claims = null;
        try {
            // After the token has expired, the token will be ExpiredJwtException exception will be thrown.
            claims = Jwts.parser().setSigningKey(KEY).parseClaimsJws(token).getBody();
        }catch (ExpiredJwtException e){
            return 2;
        }
        // Obtain the user name from the token after the user passes the query
        String username = claims.getSubject();
        User user = userService.selectUserByName(username);
        if(user ! =null) {return 1;
        }else{
            return 0; }}}Copy the code

Interceptor setup

Here is the need to use the interceptor, mainly after the processing, login after some requests need token, so here is to check.

package com.huterox.whiteholeboot.Config;

import com.alibaba.fastjson.JSON;

import com.huterox.whiteholeboot.utils.TokePassJson.TokenPassJson;
import com.huterox.whiteholeboot.utils.TokenProccessor.TokenProccessor;

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

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

@Component
public class TokenInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,Object handler)throws Exception{
        if(request.getMethod().equals("OPTIONS")){
            response.setStatus(HttpServletResponse.SC_OK);
            return true;
        }
        response.setCharacterEncoding("utf-8");
        String token = request.getHeader("token");
        int result = 0;
        if(token ! =null){
            result = TokenProccessor.verify(token);
            if(result == 1){
                System.out.println("Pass the interceptor.");
                return true;
            }

        }
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        try{
            TokenPassJson json = new TokenPassJson();
            json.setSuccess(result);//0 indicates that the authentication fails, and 2 indicates that the authentication expires
            response.getWriter().append(JSON.toJSONString(json));
            System.out.println("Authentication failed. Interceptor failed.");
        }catch (Exception e){
            e.printStackTrace();
            response.sendError(500);
            return false;
        }
        return false; }}Copy the code
package com.huterox.whiteholeboot.Config;

import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ConcurrentTaskExecutor;
import org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;

@Configuration
public class TokenConfig implements WebMvcConfigurer {




// @Override
// public void addCorsMappings(CorsRegistry registry) {
// registry.addMapping("/**")
// .allowCredentials(true)
// .allowedHeaders("*")
// .allowedMethods("*")
// .allowedOrigins("*");
//
/ /}
   // Cross-domain, we do cross-domain at the front end, so the back end does not need to use, also for security, can not be what the cat

    @Override
    public void addInterceptors(InterceptorRegistry registry){
        List<String> excludePath = new ArrayList<>();
        // Exclude blocking, except registration login (no token at this point), all other blocking
        excludePath.add("/regist");  / / login
        excludePath.add("/login");     / / register
        excludePath.add("/static/**");  // Static resources
        excludePath.add("/assets/**");  // Static resources

        registry.addInterceptor(new TokenInterceptor())
                .addPathPatterns("/ * *")
                .excludePathPatterns(excludePath);
        WebMvcConfigurer.super.addInterceptors(registry); }}Copy the code

After that, happy can visit.

conclusion

I’m running a little slow. I can’t get started. This is if feel this article is good please give praise praise ~ (white piao shameful, especially the collection also dare not praise praise (next collection number > praise? Charge: free))