SpringBoot front-end separation entry-level project from scratch (3)

Entity class writing

In the previous article, we have completed the construction of the project directory and basic framework. Now we start to write the entity class. First, we create a pojo subpackage under the model package.
Note : There are already a lot of information on the concept of PO, VO, POJO, DTO, etc. on the Internet. The detailed meaning will not be explained in this project, and only POJO and DTO are divided for convenience. Some of these are ambiguous or Readers forgive me for the wrong division method or usage.
After creating the sub-package, we create the corresponding pojo, a table corresponds to a class, if the students who have written a Web project should be familiar with this step, the author will not explain the process of creating the corresponding class one by one, please refer to the author On the GitHub homepage of GitHub, the complete directly imported project code will be uploaded later. After creation, please be sure to add the three annotations @Data, @AllArgsConstructor, and @NoArgsConstructor.
pojo created

Use Token for user authentication

After the entity class was written, we began to write the user authority authentication function. In this project, we used jwt and interceptor to implement it.
First, there are only three roles in this project:

  1. Lab Administrator (ADMIN)
  2. Laboratory member (VIP)
  3. Ordinary user (MEMBER)

This division method is not rigorous and safe enough. The current division of permissions is generally divided into two parts: user roles and user permissions. Each user corresponds to a certain role, and a certain role has certain permissions. Readers are welcome to think about it and make it more perfect. Permission division scheme.

Create Jwt tool class

First, let's go to the util package and create a class named JwtUtil. The content of the class is as follows:
JwtUtil

/**
 * @Author Alfalfa99
 * @Date 2020/9/13 15:54
 * @Version 1.0
 * JWT生成以及校验工具类
 */

@ConfigurationProperties("jwt.config")
@Component
public class JwtUtil {
    
    
    private String key;
    private long ttl;

    public String getKey() {
    
    
        return key;
    }

    public void setKey(String key) {
    
    
        this.key = key;
    }

    public long getTtl() {
    
    
        return ttl;
    }

    public void setTtl(long ttl) {
    
    
        this.ttl = ttl;
    }

    /**
     * 生成JWT
     *
     * @param id
     * @return
     */
    public String createJWT(String id, String roles) {
    
    
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        JwtBuilder builder = Jwts.builder().setId(id)	//在这里我们将用户的id存入Jwt中,方便后续使用
                .setIssuedAt(now)
                .signWith(SignatureAlgorithm.HS256, key).claim("roles", roles); //在这里我们将用户的角色存入Jwt中,方便后续鉴权,如果想存别的内容也可以往里写
        if (ttl > 0) {
    
    
            builder.setExpiration(new Date(nowMillis + ttl));
        }
        return builder.compact();
    }

    /**
     * 解析JWT
     *
     * @param jwtStr
     * @return
     */
    public Claims parseJWT(String jwtStr) {
    
    
        return Jwts.parser()
                .setSigningKey(key)
                .parseClaimsJws(jwtStr)
                .getBody();
    }
}

The key is a ciphertext used for encryption on the server, which is usually randomly generated. ttl is the expiration time of the token. Please refer to the detailed principle of the token by yourself. The space is limited and will not be repeated. Here we use @ConfigurationProperties("jwt.config")annotations to read the following configuration from the application.yml configuration file and automatically inject fields

jwt:
  config:
    key: SecretKey #服务端加密所使用的密文(自拟)
    ttl: 21600000 #毫秒
#请将该段复制至application.yml以便于能够启动项目

Back to the token, the token is generated by the user after successfully logging in and reading the user's role and id. The generated token should be returned to the front end after the login is successful, and the front end should bring this token every time it accesses the interface.
Note : Never use tokens to store sensitive user information, tokens can only be used to avoid tampering, not encryption! The content carried by the token itself can be directly parsed without the server secret key! ! !
At this time we can instantiate JwtUtil and use createJWT to generate token or parseJWT to parse token

Use interceptor (interceptor) to achieve user access interception and authentication

In the above, we have been able to parse and generate a token, but if we re-parse the token on each interface for authorization authentication, it will be too cumbersome and degrade server performance. Readers who have previous experience in writing JavaEE projects should have learned filters (Filter), the interceptor is a component similar to the Filter provided by the Spring framework, but the interceptor has more and more powerful functions, not much to say directly to the code, first we create one in the same level directory of the main startup class The interceptor package is used to store our interceptor and create a class called Tokeninterceptor under this package. The content of the class:

/**
 * @Author Alfalfa99
 * @Date 2020/9/13 18:18
 * @Version 1.0
 * 全局校验Token
 */
@Component
public class TokenInterceptor implements HandlerInterceptor {
    
    

    private final JwtUtil jwtUtil;

    public TokenInterceptor(JwtUtil jwtUtil) {
    
    
        this.jwtUtil = jwtUtil;
    }

    /**
     * 通过拦截器对请求头进行校验
     *
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
    
    
        String header = request.getHeader("Authorization");
        if (header != null && !"".equals(header)) {
    
    
            if (header.startsWith("Bearer ")) {
    
    
                //获得token
                String token = header.substring(7);
                //验证token
                try {
    
    
                    Claims claims = jwtUtil.parseJWT(token);
                    String roles = (String) claims.get("roles");
                    if (roles != null) {
    
    
                        request.setAttribute("uid",claims.getId());
                        request.setAttribute("roles",roles);
                        return true;
                    } else {
    
    
                        throw new BadCredentialsException("令牌已失效");
                    }
                } catch (Exception e) {
    
    
                    throw new BadCredentialsException("令牌已失效");
                }
            }
        }
        throw new AuthenticationCredentialsNotFoundException("请先登录");
    }
}

The token should be placed in the request header each time the front end requests the key name Authorization, and the value is Bearer Token(Token is the token generated by the server).

First, we use @Componentannotations to register the class as a Spring container, then use the class implements HandlerInterceptorthe interface, preHandle that we are processed before the target method is executed. We first inject JwtUtil through the constructor for subsequent use, and then read the token from the request header. If the token is empty, it means that the user has not logged in. Just throw an exception. If there is an error in parsing the token, throw an error directly. OK. The main idea of ​​this part is to return to the front-end error message if the content of the token cannot be parsed correctly, and let the front-end jump to the login page to log in again. If the two stored user id and user role can be correctly parsed The content is added to the request field, and we can read the user id uidand user role directly from the request in the interface roles.
In this way, we can judge whether the user has logged in each time we visit, and we store the user id and user role in the request to facilitate our subsequent controller development.

Write InterceptorConfig

After completing the preparation of the TokenInterceptor class, our content on Token authentication is basically over. Of course, we also need to write an InterceptorConfig class to configure our interceptor. Then we create a class named InterceptorConfig in the config package. The content is as follows:

/**
 * @author 苜蓿
 * @date 2020/9/13
 * 拦截器配置类
 */
@Configuration
public class InterceptorConfig extends WebMvcConfigurationSupport {
    
    

    private final TokenInterceptor tokenInterceptor;

    public InterceptorConfig(TokenInterceptor tokenInterceptor) {
    
    
        this.tokenInterceptor = tokenInterceptor;
    }


    @Override
    protected void addInterceptors(InterceptorRegistry registry) {
    
    
        //拦截所有目录,除了通向login和register的接口
        registry.addInterceptor(tokenInterceptor)
                .addPathPatterns("/**")
                .excludePathPatterns("/**/login/**", "/**/register/**")
                .excludePathPatterns("/**/*.html", "/**/*.js", "/**/*.css");
}

Then our TokenInterceptor has been configured to intercept and authenticate all access requests except html files, css files, js files, and login and registration interfaces.

Then the content of this blog has been completed, and we will start writing the controller in the next blog.

Guess you like

Origin blog.csdn.net/Alfalfa99/article/details/108712156