Blog construction and explanation


Introduction:

This blog is mainly used to record some bits related to learning and life.
This blog is relatively simple and will not be very difficult to build. The technologies involved mainly include springboot, mybatis plus, springMVC, redis, JWT,mySql, etc.
Although this blog is relatively simple, there are still holes in it!, Maybe you'll be surprised when you see it 👍

Packaging thought

  • In the controller layer, the parameters passed from the front end can be wrapped into an object using springboot to facilitate later calls. (as the domain name has not been filed, it is temporarily inconvenient to use qiniu cloud storage)

  • The return value can also be returned by another encapsulated object. Here, distinguish between the beans of the persistence layer and the beans to be returned here. The bean here is mainly used to encapsulate whatever data the front end needs. In short, this is a bean encapsulated for page requirements.
    This has great benefits. You can modify the page requirements accordingly without changing the bean corresponding to the persistence layer, so as to avoid damaging the structure in the database.
    Let's take an example from this blog. In this blog, the id of the article adopts distributed id (bigint in the database), but because the id is too long, the front end can't recognize such a long id. at this time, this idea comes in handy. Just encapsulate a bean with String id and return it to the front end.

dao layer
@Data
public class SysUser {

    private Long id;

    private String account;

    private Integer admin;

    private String avatar;

    private Long createDate;

    private Integer deleted;

    private String email;

    private Long lastLogin;

    private String mobilePhoneNumber;

    private String nickname;

    private String password;

    private String salt;

    private String status;
}
-----------------------------
vo Layer (encapsulated on demand)
@Data
public class UserVo {

    private String nickname;

    private String avatar;
    //The distributed id is relatively long, which is easy to cause accuracy loss
    //Convert to json and return to the front end to prevent accuracy loss (secondary comment)
    //@Jsonserialize (using = tostrinserializer. Class) (this method can convert Long type originally, but it is not suitable for subsequent operations, which will be described later)
    private String id;
}


redis+JWT

A brief introduction to jwt:
jwt can generate an encrypted token as a user login token. When the user logs in successfully, it will be issued to the client. When requesting a resource or interface that needs to be logged in, the token is carried, and the backend verifies whether the token is legal.
jwt consists of three parts: A.B.C
A: Header, {"type": "JWT", "alg": "HS256"} fixed
B: playload, storing information, such as user id, expiration time, etc., can be decrypted, but sensitive information cannot be stored
C: the visa is encrypted by A and B plus the secret key. It can be considered safe as long as the secret key is not lost. jwt verification is mainly to verify whether Part C is legal.
This is mainly involved at the registry.

@Service
@Transactional//All the following methods are transactions. Ensure that the methods can be executed, otherwise rollback
public class LoginServiceImp implements LoginService {
    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private RedisTemplate<String,String> redisTemplate;
    //Encryption salt can be set by yourself
    private static final String salt = "****";

    @Override
    public Result loginUser(LoginParams loginParams) {
        String account = loginParams.getAccount();
        String password = loginParams.getPassword();
        //Check whether the parameter is legal (empty)
        if(StringUtils.isBlank(account)||StringUtils.isBlank(password)){
            return Result.fail(ErrorCode.PARAMS_ERROR.getCode(),ErrorCode.PARAMS_ERROR.getMsg());
        }
        //Encrypt password
        password = DigestUtils.md5Hex(password + salt);
        //Check for
        SysUser sysUser=sysUserService.findUser(account,password);
        if(sysUser==null){
            return Result.fail(ErrorCode.ACCOUNT_PWD_NOT_EXIST.getCode(),ErrorCode.ACCOUNT_PWD_NOT_EXIST.getMsg());
        }
        //token returned after successful login
        String token = JWTUtils.createToken(sysUser.getId());
        //Store sysUser in redis (one day), reduce the pressure on the database and verify again
        redisTemplate.opsForValue().set("TOKEN_"+token, JSON.toJSONString(sysUser),1,TimeUnit.DAYS);
        return Result.success(token);
    }

    /**
     * Verify the user's token
     * @param token
     * @return
     */
    @Override
    public SysUser checkToken(String token) {
        //Check whether the token is empty
        if(StringUtils.isBlank(token))return null;
        //Resolve whether the token exists
        Map<String, Object> stringObjectMap = JWTUtils.checkToken(token);
        if(stringObjectMap==null)return null;
        //Verify and obtain objects from redis
        String s = redisTemplate.opsForValue().get("TOKEN_"+token);
        if(StringUtils.isBlank(s))return null;
        else return JSON.parseObject(s,SysUser.class);
    }

    @Override
    public Result logout(String token) {
        redisTemplate.delete("TOKEN_"+token);
        return Result.success(null);
    }

    /**
     * User registration
     * @param loginParams
     * @return
     */
    @Override
    public Result registerUser(LoginParams loginParams) {
        String account = loginParams.getAccount();
        String password = loginParams.getPassword();
        String nickname = loginParams.getNickname();
        //Check whether the parameter is empty
        if(StringUtils.isBlank(account)||StringUtils.isBlank(password)||StringUtils.isBlank(nickname)){
            return Result.fail(ErrorCode.PARAMS_ERROR.getCode(), ErrorCode.PARAMS_ERROR.getMsg());
        }
        //Check whether the account exists
        SysUser sysUser=sysUserService.findUserByAccount(account);
        if(sysUser!=null){
            return Result.fail(ErrorCode.Account_Exist.getCode(), ErrorCode.Account_Exist.getMsg());
        }
        //Fill in user information
        sysUser = new SysUser();
        sysUser.setNickname(nickname);
        sysUser.setAccount(account);
            //Note that the password is encrypted and saved
        sysUser.setPassword(DigestUtils.md5Hex(password+salt));
        sysUser.setCreateDate(System.currentTimeMillis());
        sysUser.setLastLogin(System.currentTimeMillis());
        sysUser.setAvatar("/static/img/logo.b3a48c0.png");
        sysUser.setAdmin(1); //1 is true
        sysUser.setDeleted(0); // 0 is false
        sysUser.setSalt("");
        sysUser.setStatus("");
        sysUser.setEmail("");
        //Save user
        sysUserService.save(sysUser);
        //Generate a token and save it to redis
        String token = JWTUtils.createToken(sysUser.getId());
        redisTemplate.opsForValue().set("TOKEN_"+token,JSON.toJSONString(sysUser),1,TimeUnit.DAYS);
        return Result.success(token);
    }

    public static void main(String[] args) {
        System.out.println(DigestUtils.md5Hex("123456" + salt));
    }
}

  • First, the encrypted password is stored in the database, and the encrypted password is also verified during verification to ensure password security.
  //Encrypt password
        password = DigestUtils.md5Hex(password + salt);
        //Check for
        SysUser sysUser=sysUserService.findUser(account,password);
  • Redis is used for caching and enhanced verification. User objects are stored in redis regularly and directly obtained from redis when needed in the later stage, which greatly improves the operation efficiency.
        //token returned after successful login
        String token = JWTUtils.createToken(sysUser.getId());
        //Store sysUser in redis (one day), reduce the pressure on the database and verify again
        redisTemplate.opsForValue().set("TOKEN_"+token, JSON.toJSONString(sysUser),1,TimeUnit.DAYS);
//JSON.parseObject(s,SysUser.class); You can put it to get the object
        return Result.success(token);

Check the token and get the object. This is mainly used in the interceptor to restrict some operations of the user. For example, you can write articles only when you are logged in

@Override
    public SysUser checkToken(String token) {
        //Check whether the token is empty
        if(StringUtils.isBlank(token))return null;
        //Resolve whether the token exists
        Map<String, Object> stringObjectMap = JWTUtils.checkToken(token);
        if(stringObjectMap==null)return null;
        //Verify and obtain objects from redis
        String s = redisTemplate.opsForValue().get("TOKEN_"+token);
        if(StringUtils.isBlank(s))return null;
        else return JSON.parseObject(s,SysUser.class);
    }

JwtUtil related codes

public class JWTUtils {
    //The key can be set by yourself
    private static final String jwtToken = "******";

    //Generate token
    public static String createToken(Long userId){
        //Part B
        Map<String,Object> claims = new HashMap<>();
        claims.put("userId",userId);
        //Part C
        JwtBuilder jwtBuilder = Jwts.builder()
                .signWith(SignatureAlgorithm.HS256, jwtToken) // Issuing algorithm, the secret key is jwtToken
                .setClaims(claims) // body data should be unique and set by yourself
                .setIssuedAt(new Date()) // Set issuing time
                .setExpiration(new Date(System.currentTimeMillis() + 24 * 60 * 60 * 60 * 1000));// Effective time of day
        String token = jwtBuilder.compact();
        return token;
    }
    //analysis
    public static Map<String, Object> checkToken(String token){
        try {
            Jwt parse = Jwts.parser().setSigningKey(jwtToken).parse(token);
            return (Map<String, Object>) parse.getBody();
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }
}

This article ends here 🌹

Keywords: Java Database Spring

Added by jdadwilson on Fri, 17 Dec 2021 17:34:57 +0200