Rumah > Java > javaTutorial > Bagaimanakah Spring Boot mengintegrasikan JWT untuk mencapai pengesahan bahagian hadapan dan belakang?

Bagaimanakah Spring Boot mengintegrasikan JWT untuk mencapai pengesahan bahagian hadapan dan belakang?

WBOY
Lepaskan: 2023-05-18 13:19:06
ke hadapan
1450 orang telah melayarinya

Pengenalan kepada JWT

JWT (nama penuh: Json Web Token) ialah standard terbuka (RFC 7519) yang mentakrifkan cara yang ringkas dan serba lengkap untuk berkomunikasi antara pihak sebagai objek JSON dengan selamat antara

Mengapa menggunakan JWT

Apakah kelemahan pengesahan sesi tradisional?

  • Maklumat log masuk setiap pengguna akan disimpan dalam Sesi pelayan Apabila bilangan pengguna bertambah, overhed pelayan akan meningkat dengan ketara.

  • Maklumat sesi disimpan dalam memori pelayan, yang boleh menyebabkan kegagalan untuk aplikasi yang diedarkan Walaupun maklumat sesi boleh disimpan secara seragam dalam cache Redis, ini boleh meningkatkan kerumitan seks.

  • Memandangkan pengesahan Sesi adalah berdasarkan Kuki, ia tidak terpakai kepada terminal bukan penyemak imbas dan mudah alih.

  • Sistem pemisahan bahagian hadapan dan bahagian belakang, kerana bahagian hadapan dan bahagian belakang ialah domain silang dan maklumat kuki tidak boleh dipalang, jadi pengesahan sesi tidak boleh diteruskan silang -pengesahan domain.

Kelebihan pengesahan JWT

  • Mudah: Jumlah data JWT Token adalah kecil dan kelajuan penghantaran adalah pantas.

  • Merentas bahasa: Token JWT disimpan pada klien dalam bentuk yang disulitkan JSON, jadi JWT ialah bahasa silang dan disokong oleh mana-mana borang web. Cross-platform: tidak bergantung pada kuki dan sesi, dan tidak perlu menyimpan maklumat sesi pada pelayan Ia sangat sesuai untuk aplikasi yang diedarkan dan boleh digunakan untuk pengembangan.

Struktur data JWT

Bagaimanakah Spring Boot mengintegrasikan JWT untuk mencapai pengesahan bahagian hadapan dan belakang?

Pengepala

Bahagian pertama JWT ialah bahagian pengepala, iaitu perihalan JWT A Json objek metadata, biasanya seperti yang ditunjukkan di bawah.

{
    "alg": "HS256",
    "typ": "JWT"
}
Salin selepas log masuk

Atribut alg menunjukkan algoritma yang digunakan untuk tandatangan lalai ialah HMAC SHA256 (ditulis sebagai HS256 Atribut taip menunjukkan jenis token JWT secara seragam.

Payload

Bahagian kedua JWT ialah Payload, yang juga merupakan objek Json Selain mengandungi data yang perlu dihantar, terdapat tujuh medan lalai untuk dipilih. iss: penerbit exp: masa tamat sub: topik aud: pengguna nbf: tidak tersedia sebelum iat: masa penerbitan jti: JWT ID digunakan untuk mengenal pasti JWT ini

{
    //默认字段
    "sub":"主题123",
    //自定义字段
    "name":"java",
    "isAdmin":"true",
    "loginTime":"2021-12-05 12:00:03"
}
Salin selepas log masuk

Perlu diingat bahawa secara lalai JWT tidak disulitkan dan sesiapa sahaja boleh mentafsir kandungannya, jadi jika anda mempunyai beberapa maklumat sensitif, jangan simpannya di sini untuk mengelakkan kebocoran maklumat. Objek JSON juga ditukar kepada rentetan menggunakan algoritma URL Base64 dan disimpan.

Tandatangan

Bahagian cincang tandatangan adalah untuk menandatangani dua bahagian data di atas Ia perlu menggunakan pengepala dan data muatan yang dikodkan base64 dan menjana cincang melalui algoritma yang ditentukan untuk memastikan bahawa. data tidak akan diusik.

Spring Boot menyepadukan JWT

Memperkenalkan pakej Jwt

<dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt</artifactId>
        <version>0.9.1</version>
  </dependency>
Salin selepas log masuk

Menulis jwt kelas alat

public class JwtUtil
{
//创建jwt
public static String createJWT(String subject, String issue, Object claim,
            long ttlMillis)
    {
       //当前时间
        long nowMillis = System.currentTimeMillis();
        //过期时间
        long expireMillis = nowMillis + ttlMillis;
        String result = Jwts.builder()
                .setSubject(subject) //设置主题
                .setIssuer(issue) //发行者
                .setId(issue)//jwtID
                .setExpiration(new Date(expireMillis)) //设置过期日期
                .claim("user", claim)//主题,可以包含用户信息
                .signWith(getSignatureAlgorithm(), getSignedKey())//加密算法
                .compressWith(CompressionCodecs.DEFLATE).compact();//对载荷进行压缩

        return result;
    }
    
    // 解析jwt
    public static Jws<Claims> pareseJWT(String jwt)
    {
        Jws<Claims> claims;
        try
        {
            claims = Jwts.parser().setSigningKey(getSignedKey())
                    .parseClaimsJws(jwt);
        }
        catch (Exception ex)
        {
            claims = null;
        }
        return claims;
    }

   //获取主题信息
    public static Claims getClaims(String jwt)
    {
        Claims claims;
        try
        {
            claims = Jwts.parser().setSigningKey(getSignedKey())
                    .parseClaimsJws(jwt).getBody();
        }
        catch (Exception ex)
        {
            claims = null;
        }
        return claims;
    }
  }
  
   /**
     * 获取密钥
     * 
     * @return Key
     */
    private static Key getSignedKey()
    {
        byte[] apiKeySecretBytes = DatatypeConverter
                .parseBase64Binary(getAuthKey());
        Key signingKey = new SecretKeySpec(apiKeySecretBytes,
                getSignatureAlgorithm().getJcaName());
        return signingKey;
    }
    
    private static SignatureAlgorithm getSignatureAlgorithm()
    {
        return SignatureAlgorithm.HS256;
    }
  
  //获取密钥,可以动态配置
  public static String getAuthKey()
  {
        String auth = "123@#1234";
  }
Salin selepas log masuk

Pemintas pengesahan token

 Component
public class TokenInterceptor extends HandlerInterceptorAdapter
{
    public static Log logger = LogManager.getLogger(TokenInterceptor.class);

    @Override
    public boolean preHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler) throws Exception
    {
        String uri = request.getRequestURI();
        logger.info("start TokenInterceptor preHandle.." + uri);
         
		//需要过滤特殊请求
        if (SystemUtil.isFree(uri) || SystemUtil.isProtected(uri))
        {
            return true;
        }
        
		
        String metohd=request.getMethod().toString();
        logger.info("TokenInterceptor request method:"+metohd);
        //options 方法需要过滤
        if("OPTIONS".equals(metohd))
        {
            return true;   
        }
        
		//是否开启token认证
        boolean flag = SystemUtil.getVerifyToken();
        ResponseResult result = new ResponseResult();
		//从请求的head信息中获取token
        String token = request.getHeader("X-Token");

        if (flag)
        {
            if(StringUtils.isEmpty(token))
            {
                token=request.getParameter("X-Token");    
            }
            // token不存在
            if (StringUtils.isEmpty(token))
            {
                result.setCode(ResultCode.NEED_AUTH.getCode());
                result.setMsg(ResultCode.NEED_AUTH.getMsg());
                WebUtil.writeJson(result, response);
                return false;
            }
            else
            {
                Claims claims = JwtUtil.getClaims(token);
                String subject = "";
                if (claims != null)
                {
                    subject = claims.getSubject();
                    // 验证主题
                    if (StringUtils.isEmpty(subject))
                    {
                        result.setCode(ResultCode.INVALID_TOKEN.getCode());
                        result.setMsg(ResultCode.INVALID_TOKEN.getMsg());
                        WebUtil.writeJson(result, response);
                        return false;
                    }								
                }
                else
                {
                    result.setCode(ResultCode.INVALID_TOKEN.getCode());
                    result.setMsg(ResultCode.INVALID_TOKEN.getMsg());
                    WebUtil.writeJson(result, response);
                    return false;
                }
            }
        }
        return true;
    }

}
Salin selepas log masuk
Configuring Peranti

@Configuration
public class WebConfig implements WebMvcConfigurer
{
    @Resource
    private TokenInterceptor tokenInterceptor;

    public void addInterceptors(InterceptorRegistry registry)
    {
        registry.addInterceptor(tokenInterceptor).addPathPatterns("/**");
    }
 }
Salin selepas log masuk

Proses pengesahan log masuk

Bagaimanakah Spring Boot mengintegrasikan JWT untuk mencapai pengesahan bahagian hadapan dan belakang?

Kod contoh

@RequestMapping("login")
public Result login(HttpServletResponse response)
{
    Map<String, Object> map = new HashMap<>();
    //
    Result result = loginAuth(user);
    int code = result.getCode();
            //登录认证成功
    if (code ==ResultCode.SUCCESS)
    {
        //默认为7天
        Long ttlMillis = 7*1000 * 60 * 60 * 24;
        //过期时间
        long expreTime = System.currentTimeMillis() + ttlMillis;
        String tokenKey = UUID.randomUUID().toString();
        String tokenId = JwtUtil.createJWT(user.getUserId(), tokenKey,
                user.getPassword(), expreTime);                   
        map.put("expreTime", expreTime);				
        map.put("tokenId", tokenId);           
    }
    else
    {
        logger.error("login error:" +FastJsonUtil.toJSONString(result));
    }
    return result;
}
Salin selepas log masuk

Atas ialah kandungan terperinci Bagaimanakah Spring Boot mengintegrasikan JWT untuk mencapai pengesahan bahagian hadapan dan belakang?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Label berkaitan:
sumber:yisu.com
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan