1. 程式人生 > >在spring boot專案中加入 JWT

在spring boot專案中加入 JWT

將JWT放到專案中作為一個引數被掉用發起者傳過來作為介面呼叫的口令

<!-- https://mvnrepository.com/artifact/com.auth0/java-jwt -->
<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>3.4.0</version>
</dependency>

編寫Jwt服務:

package com.
shengqian.demo.service; public interface JwtService { String getJwtsString(String ip); } package com.shengqian.demo.service.impl; import com.shengqian.demo.JwtUserName; import com.shengqian.demo.Util.JwtUser; import com.shengqian.demo.Util.JwtUtil; import com.shengqian.demo.service.JwtService;
import org.springframework.stereotype.Service; import java.sql.Timestamp; /** * ClassName JwtServiceImpl * Description TODO * Auther chaoj * Date 2018/12/17 16:18 * Version 1.0 **/ @Service public class JwtServiceImpl implements JwtService { @Override public String getJwtsString(String ip)
{ Timestamp timestamp = new Timestamp(System.currentTimeMillis()); JwtUser user = new JwtUser.Builder(JwtUserName.ADMIN.getUsername(), timestamp) .ip(ip) .password(JwtUserName.ADMIN.getInfo()).build(); long ttlMillis = 30*60; String jwt = JwtUtil.createJwt(ttlMillis, user); return jwt; } }

再貼上JwtUser和JwtUtil的程式碼,分別是介面呼叫的使用者和Jwt生成的工具類

package com.shengqian.demo.Util;


import java.sql.Timestamp;

/**
 * ClassName JwtUser
 * Description TODO
 * Auther chaoj
 * Date 2018/12/17 10:30
 * Version 1.0
 **/
public class JwtUser {
    private final String ip ;
    private final String username ;
    private final String password ;
    private final Timestamp timestamp;

    public static class Builder{
        private String ip = "0.0.0.0";
        private String username;
        private String password = "";
        private Timestamp timestamp ;

        public Builder(String username, Timestamp timestamp){
            this.username = username;
            this.timestamp = timestamp;
        }

        public Builder ip(String val){
            ip = val;
            return this;
        }
        public Builder password(String val){
            password = val;
            return this;
        }

        public JwtUser build(){return new JwtUser(this);}
    }

    public JwtUser(Builder builder){
        ip = builder.ip;
        username = builder.username;
        password = builder.password;
        timestamp = builder.timestamp;
    }

    public String getPassword() {
        return password;
    }

    public Timestamp getTimestamp() {
        return timestamp;
    }

    public String getIp() {
        return ip;
    }

    public String getUsername() {
        return username;
    }
}
//JwtUser 的構造器採用Builder模式,這樣可以有效檢查引數,同時也是《Effective Java》推薦的寫法
package com.shengqian.demo.Util;


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;
import java.util.UUID;

/**
 * ClassName JwtUtil
 * Description TODO
 * Auther chaoj
 * Date 2018/12/17 10:49
 * Version 1.0
 **/
public class JwtUtil {

    public static String createJwt(long ttlMillis, JwtUser user){
    /**
     * @description TODO 建立jwt
     * @author chaoj
     * @date 2018/12/17 11:03
     * @Param [ttlMillis, user]
     * @return java.lang.String
     * @version 1.0
     **/
        SignatureAlgorithm algorithm = SignatureAlgorithm.HS256;
        long millis = System.currentTimeMillis();
        Date date = new Date(millis);
        Map<String, Object> claims = new HashMap<String, Object>();
        claims.put("ip", user.getIp());
        claims.put("username", user.getUsername());
        claims.put("timestamp", user.getTimestamp());
        String key = user.getPassword();
        String subject = user.getUsername();
        JwtBuilder jwtBuilder = Jwts.builder().signWith(algorithm, key)
                                    .setClaims(claims)
                                    .setId(UUID.randomUUID().toString())
                                    .setIssuedAt(date)
                                    .setSubject(subject);
        if (ttlMillis > 0){
            long millisExp = millis + ttlMillis;
            Date expdete = new Date(millisExp);
            jwtBuilder.setExpiration(expdete);
        }
        return jwtBuilder.compact();
    }



    public static Claims parseJwt(String token, JwtUser user){
        /**
         * @description TODO 解析
         * @author chaoj
         * @date 2018/12/17 11:07
         * @Param [token, user]
         * @return io.jsonwebtoken.Claims
         * @version 1.0
         **/
        String key = user.getPassword();
        Claims claims = Jwts.parser()
                .setSigningKey(key)
                .parseClaimsJws(token).getBody();
        return claims;
    }

    public static Boolean isVerify(String token, JwtUser user){
        String key = user.getPassword();
        Claims claims = Jwts.parser()
                        .setSigningKey(key)
                        .parseClaimsJws(token).getBody();
        if (claims.get("password").equals(user.getPassword())){
            return true;
        }
        return false;
    }
}


然後寫控制器方法

@RequestMapping(value = Path.LOGIN, method = RequestMethod.POST)
    @ResponseBody
    public Map<String, Object> userLogin(@RequestParam("phone") final String phone,
                                         @RequestParam("password") final String password,
                                         @RequestParam("ip") final String ip){
        Map<String, Object> ans = new HashMap<>();
        UserInfoDto dto = userInfoService.getUser(phone);
        if (!dto.isRegister()){
            dto.setPassword(password);
            UserInfoDto dto1 = userInfoService.checkPassword(dto);
            if (dto1.isVoladate()){
                ans.put("code", 200);
                ans.put("info", "成功");
                ans.put("key", jwtService.getJwtsString(ip));
                return ans;
            }
        }
        ans.put("code", 400);
        ans.put("info", "使用者名稱或密碼錯誤");
        return ans;
    }

如果登入成功,返回一個key,作為介面呼叫的令牌。在我的設計中,jwt將被存放在分散式快取和本地LRU快取中,每次請求過來,先判斷當前伺服器快取中是否有這個key,如果沒有,就去問redis就行了。下一部分我將做把redis整合到spring boot中。

返回demo

{
    "code": 200,
    "key": "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJjaGFvamlsYWppIiwiaXAiOiI2MS4xODYuMTg1LjE4MCIsImV4cCI6MTU0NTAzNjQyOCwiaWF0IjoxNTQ1MDM2NDI2LCJqdGkiOiIxNTUzY2JmMC1jMDBiLTQxZmQtOTdiYy1jM2Q3ZTBhMDM2ZDQiLCJ1c2VybmFtZSI6ImNoYW9qaWxhamkiLCJ0aW1lc3RhbXAiOjE1NDUwMzY0MjY5MTd9.w-XmT9yy7JVVJQt6wIJLjcpVfhN0EVZvc-MpMLVwN58",
    "info": "成功"
}