Encryption of login information and access rights

Posted by bettydailey on Sat, 18 Sep 2021 15:04:30 +0200

Encryption of user password: during user registration, query whether the user exists in the database according to the transmitted information. If it does not exist, encrypt its password. The encrypted information is stored in the database. When logging in, encrypt the login password again and verify it with the encrypted information in the database

If you only want to know about information encryption, you can skip the related operations of filter and token generation tools.......

Project structure:

 

 

 

User entity class:

The corresponding getter and setter methods are not displayed!!!

import com.fasterxml.jackson.annotation.JsonFormat;
import java.io.Serializable;
import java.time.LocalDateTime;

public class User implements Serializable {
    private static final long serialVersionUID=1L;
    //Primary key number
    private Long id;

    /*user name*/
    private String username;

    /*password*/
    private String password;

    /*nickname*/
    private String nickname;

    /*Gender*/
    private Integer sex;

    /*full name*/
    private String name;

    /*Creation time*/
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createTime;

controller layer:

There are two methods: login and registration. Login also involves the generation of token, which is described below

package com.example.demo.controller;

import com.example.demo.entity.User;
import com.example.demo.service.UserService;
import com.example.demo.utils.Result;
import com.example.demo.utils.ZbLpFileUtils;
import com.mysql.cj.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;

@Controller
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userservice;

    /**
     * register
     * */
    @ResponseBody
    @PostMapping("/register")
    public Map register(@RequestBody User user){
        //Judge whether the parameter is empty
        if (StringUtils.isNullOrEmpty(user.getUsername())) return Result.errorInput("User name is empty");
        if (StringUtils.isNullOrEmpty(user.getPassword())) return Result.errorInput("Password is empty");
        return userservice.register(user);
    }

    /**
     * land
     * */
    @ResponseBody
    @PostMapping("/login")
    public Map login(@RequestBody User user, HttpServletRequest request){
        //Judgment parameters
        if (StringUtils.isNullOrEmpty(user.getUsername())) return Result.errorInput("user name");
        if (StringUtils.isNullOrEmpty(user.getPassword())) return Result.errorInput("password");

        return userservice.login(user,request.getSession());
    }
}

service layer:

import com.example.demo.entity.User;
import javax.servlet.http.HttpSession;
import java.util.List;
import java.util.Map;
public interface UserService {
    /**
     * register
     * */
    Map register(User user);
    /**
     * land
     * */
    Map login(User user, HttpSession session);
}

imp layer:

This layer is mainly used to extract data from the database and verify the extracted data with the transmitted value. In addition, there is a tool class, Md5Utils, which is mainly responsible for password encryption

Md5Utils class:

import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class Md5Utils {
    /**
     * MD5 encryption
     * */
    public static String md5(String str){
        try {
            //Generate an Md5 encryption calculation, MessageDigest.getInstance(), and you can choose other encryption methods
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            //Calculate MD5 function, parameter: String to be encrypted converted into bytes
            md5.update(str.getBytes());
            //It's a byte type array. In short, printing out is a bunch of things you can't understand
            byte[] digest = md5.digest();
            //An encrypted String type information is generated to convert the symbol size representation of BigInteger into a BigInteger value
            //BigInteger(int signum, byte[] magnitude):
            return new BigInteger(1,md5.digest()).toString(16);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return null;
        }
    }

}

Explanation of login operation: in the login operation, there will be an operation to generate a token. Why should a token be generated when logging in? In a website, you can set access permissions. In addition to the login and registration functions, you can set no token login (how do you log in when you set access permissions?), other functions must be accessed by token, otherwise others can access your personal information at will. This token is like a key. Without this key, you can't open the corresponding lock and access the corresponding Controller resources!!!

The token is stored in the request header and needs to be set using the test interface

You are not allowed to access the controller at will. You need to set a filter. In addition, this is a back-end and does not involve the front-end. Therefore, to achieve access filtering, you need to use a test interface. This test interface is not described here.

Filter code:

import com.alibaba.fastjson.JSON;
import com.example.demo.utils.LpJwTokenUtils;
import com.example.demo.utils.Result;
import com.github.isrsal.logging.RequestWrapper;
import com.github.isrsal.logging.ResponseWrapper;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
 * filter
 * */
@Component
public class LpFilter implements Filter {


    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        HttpServletRequest request = (HttpServletRequest) req;

        ResponseWrapper responseWrapper = new ResponseWrapper(Thread.currentThread().getId(), response);
        RequestWrapper requestWrapper = new RequestWrapper(Thread.currentThread().getId(), request);

        requestWrapper.setCharacterEncoding("UTF-8");

        HttpSession session = request.getSession();

        //Set the allowed cross domain configuration
        // Fill in the allowed cross domain host IP here (you can dynamically configure the specific allowed domain name and IP when you officially go online)
        responseWrapper.setHeader("Access-Control-Allow-Origin", "*");
        // Allowed access methods
        responseWrapper.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE,PUT");
        // Access control Max age is used to cache CORS related configurations
        responseWrapper.setHeader("Access-Control-Max-Age", "3600");
        //Information that the requestor is allowed to carry in the header
        responseWrapper.setHeader("Access-Control-Allow-Headers", "Content-Type, Access-Control-Allow-Headers, Authorization");
        //Set encoding format
        responseWrapper.setCharacterEncoding("UTF-8");
        responseWrapper.setContentType("application/json; charset=utf-8");

        //Get uri address - interface address
        String requestURI = requestWrapper.getRequestURI();
        //Determine the address that can be filtered
        if(isUri(requestURI)){
            //Allow requests to access the controller
            chain.doFilter(requestWrapper,responseWrapper);
        }else{
            //Return map
            Map<String,Object> result=null;
            boolean isFilter=false;
            //Get token
            String token=requestWrapper.getHeader("Authorization");
            //Verify whether the token is valid
            if(token==null ||token.trim().isEmpty()){
                result= Result.errorToken("token non-existent");

            }else if(!token.equals(session.getAttribute(LpJwTokenUtils.getTokenSubject(token)))){
                result=Result.errorToken("token invalid");
            }else if(LpJwTokenUtils.isExpiration(token)){
                result=Result.errorInput("token be overdue");
            }else{
                isFilter=true;
            }
            //adopt
            if (isFilter){
                chain.doFilter(requestWrapper,responseWrapper);
            }else{
                //Return error
                PrintWriter writer =null;
                OutputStreamWriter osw=null;
                try {
                    //Create an output stream and set the encoding format
                    osw=new OutputStreamWriter(response.getOutputStream(),"UTF-8");
                    //Create character print stream object
                    writer=new PrintWriter(response.getOutputStream(),true);
                    //Convert to json character transfer and output
                    writer.write(JSON.toJSONString(result));
                }finally {
                    if (writer!=null) writer.close();
                    if (osw!=null) osw.close();
                }

            }
        }


    }


    /**
     * It is an interface that can be passed through
     * */
    private boolean isUri(String requestUri){
        List<String> list=new ArrayList<>();
        list.add("user/register");//register
        list.add("user/login");//land
        for (String s : list) {
            if (requestUri.indexOf(s)>-1) return true;
        }
        return false;
    }

    @Override
    public void destroy() {

    }
}

The parameters needed to generate a token here are: user id, user name and password. Therefore, an LpTokenLogin class is written to store these three parameters,

LpTokenLogin class:

public class LpTokenLogin {
    private static final long  serialVersionUId=1L;
    /*Primary key number*/
    private Long id;
    /*user name*/
    private String username;
    /*password*/
    private String password;
    /*token,After the token is generated, it is used for storing*/
    private String token;

    public LpTokenLogin() {
    }

    public LpTokenLogin(Long id, String username, String password) {
        this.id = id;
        this.username = username;
        this.password = password;
    }

Tool class for generating token: this class has four attributes, which participate in the generation of token. It contains five token methods, the creation of token, the content of token, the judgment of whether the token is expired, and the generation of topic (this is useless, that is, saving the token in the session and giving a key value) to get the topic

LpJwToken class:

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class LpJwTokenUtils {
    //The contents of these attributes can be defined by themselves
    //The key is used for decryption
    private static final String PRIMARY_KEY="key_zbxxxx";
    //Issuer
    private static final String ISS="Gent.Ni";
    //Add role key
    private static final String TOKEN_INFO="tokenInfo";
    //The expiration time is 3600 seconds * 24 hours
    public static final Long EXPIRATION=3600L*24;
    /**
     * Create token
     * character string
     * Entity object
     * */
    public static String createToken(String str,Object object){
        Map<String,Object> map=new HashMap<>();
        map.put(TOKEN_INFO,object);
        JwtBuilder builder = Jwts.builder()
                //Signature of JWT using HS512 algorithm, PRIMARY_KEY is our key
                .signWith(SignatureAlgorithm.HS512, PRIMARY_KEY)
                //Set content
                .setClaims(map)
                //Set issuer
                .setIssuer(ISS)
                //set up themes
                .setSubject(str)
                //Set publishing time
                .setIssuedAt(new Date())
                //Set time validity
                .setExpiration(new Date(System.currentTimeMillis()+EXPIRATION*1000));
        return builder.compact();
    }
    /**
     * Judge whether the token has expired
     * */
    public static boolean isExpiration(String token){
        //Judge whether the token date is less than the current date and return true (expired)
        return getTokenBody(token).getExpiration().before(new Date());
    }
    /**
     * Get theme
     * */
    public static String getTokenSubject(String token){
        return getTokenBody(token).getSubject();
    }
    /**
     * Unique theme
     * */
    public static  String getSubjectName(String name){
        return "token_subject_"+name;
    }
    /**
     * Get the contents of the token
     * */
    public static Claims getTokenBody(String token){
        return Jwts.parser().setSigningKey(PRIMARY_KEY).parseClaimsJws(token).getBody();
    }

}

UserServiceImpl implementation class:

import com.example.demo.entity.LpTokenLogin;
import com.example.demo.entity.User;
import com.example.demo.mapper.UserMapper;
import com.example.demo.service.UserService;
import com.example.demo.utils.LpJwTokenUtils;
import com.example.demo.utils.Md5Utils;
import com.example.demo.utils.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpSession;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;
    @Override
    public Map register(User user) {
        //Query user name, cannot be duplicate
        User userName = userMapper.getUserName(user.getUsername());
        if (userName!=null) return Result.errorInput("The user name has already been registered");
        //Password encryption
        user.setPassword(Md5Utils.md5(user.getPassword()));
        //Creation time
        user.setCreateTime(LocalDateTime.now());
        //newly added
        int insert = userMapper.insert(user);
        if (insert>0){
            return Result.success(user);
        }else
            return Result.error();
    }

    @Override
    public Map login(User user, HttpSession session) {

        //Query by user name
        User u = userMapper.getUserName(user.getUsername());
        //Determine whether the password is correct
        if (u==null||u.getPassword().equals(Md5Utils.md5(user.getPassword())))
            return Result.error("The user name does not exist or the password is incorrect");
        //Return an object to store the user's id, user name and password. If not, create this class
        LpTokenLogin lpTokenLogin = new LpTokenLogin(u.getId(), u.getUsername(), u.getPassword());
        //theme
        String subjectName = LpJwTokenUtils.getSubjectName(lpTokenLogin.getId().toString());
        //Generate token
        String token = LpJwTokenUtils.createToken(subjectName, lpTokenLogin);
        //storage
        session.setAttribute(subjectName,token);

        lpTokenLogin.setToken(token);

        return Result.success(lpTokenLogin);
    }

}

A Result class is written here: it is used to return data

import java.util.HashMap;
import java.util.Map;

/**
 * return
 **/
public class Result {
    public static Map<String,Object> errorToken(String msg) {return result(999,msg,null);}
    public static Map<String,Object> errorInput(String msg){
        return error("Please enter" + msg);
    }

    public static Map<String,Object> success(){
        return result(200,"success",null);
    }
    public static Map<String,Object> success(Object o){
        return result(200,"success",o);
    }
    public static Map<String,Object> error(){
        return result(500,"fail",null);
    }
    public static Map<String,Object> error(String msg){
        return result(500,msg,null);
    }


    public static Map<String,Object> result(int code,String msg,Object o){
        Map<String,Object> map = new HashMap<>();
        map.put("code",code);
        map.put("msg",msg);
        map.put("data",o);
        return map;
    }
}

Actions on database statements:

UserMapper.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.mapper.UserMapper">
    <resultMap id="UserResult" type="com.example.demo.entity.User">
        <result property="id" column="id"/>
        <result property="username" column="username"/>
        <result property="password" column="password"/>
        <result property="nickname" column="nickname"/>
        <result property="sex" column="sex"/>
        <result property="name" column="name"/>
        <result property="createTime" column="create_time"/>
    </resultMap>

    <sql id="userSql">
        select id,username,password,nickname,sex,name,create_time from user
    </sql>
    <select id="listUser" resultMap="UserResult">
        <include refid="userSql"/>
    </select>

    <select id="getUserName" resultMap="UserResult" parameterType="String">
        <include refid="userSql"/>
        where
        username=#{username}
    </select>

    <insert id="insert" parameterType="com.example.demo.entity.User" useGeneratedKeys="true" keyProperty="id">
        insert into user
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="username !=null and username !=''">username,</if>
            <if test="password !=null and password !=''">password,</if>
            <if test="nickname !=null and nickname !=''">nickname,</if>
            <if test="sex !=null and sex !=''">sex,</if>
            <if test="name !=null and name !=''">name,</if>
            <if test="createTime !=null and createTime !=''">create_time,</if>
        </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            <if test="username !=null and username !=''">#{username},</if>
            <if test="password !=null and password !=''">#{password},</if>
            <if test="nickname !=null and nickname !=''">#{nickname},</if>
            <if test="sex !=null and sex !=''">#{sex},</if>
            <if test="name !=null and name !=''">#{name},</if>
            <if test="createTime !=null and createTime !=''">#{createTime},</if>
        </trim>
    </insert>

</mapper>

Database statement:

CREATE TABLE `user` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT 'Primary key id',
  `username` varchar(50) DEFAULT NULL COMMENT 'user name',
  `password` varchar(50) DEFAULT NULL COMMENT 'password',
  `nickname` varchar(50) DEFAULT NULL COMMENT 'nickname',
  `sex` tinyint(1) DEFAULT NULL COMMENT 'Gender (0: female 1: male)',
  `name` varchar(50) DEFAULT NULL COMMENT 'full name',
  `create_time` datetime DEFAULT NULL COMMENT 'Creation time',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=38 DEFAULT CHARSET=utf8mb3 COMMENT='User table';

/*Data for the table `user` */

insert  into `user`(`id`,`username`,`password`,`nickname`,`sex`,`name`,`create_time`) values (4,'Robin','111111','Archaeologists ',1,'Abdominal black','2021-09-02 11:41:38'),(5,'Usop','222222','shooter',1,'liar','2021-09-02 11:41:38'),(6,'Sauron','000000','Jianhao',1,'Green head','2021-09-09 16:10:02'),(7,'Monkey D Luffy','666666','One Piece',1,'goods not original','2021-09-10 10:48:05');

Corresponding application.yml configuration:

server:
  port: 8081
  tomcat:
    uri-encoding: UTF-8


spring:
    datasource:
      url: jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=Asia/Shanghai
      username: root
      password: xxxxx
      driver-class-name: com.mysql.cj.jdbc.Driver

mybatis:
  mapper-locations: classpath:mapper/*Mapper.xml
  type-aliases-package: com.example.test.entity

Corresponding pom dependencies:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.0</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <!--<scope>runtime</scope>-->
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <!--spring extend-->
        <dependency>
            <groupId>com.github.isrsal</groupId>
            <artifactId>spring-mvc-logger</artifactId>
            <version>0.2</version>
        </dependency>
        <!--JWT-->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.0</version>
        </dependency>
        <!--JSON-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.50</version>
        </dependency>

Topics: Java Maven Spring intellij-idea