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 🌹