Heim >Java >javaLernprogramm >Wie integriert Spring Boot JWT, um eine Front-End- und Back-End-Authentifizierung zu erreichen?

Wie integriert Spring Boot JWT, um eine Front-End- und Back-End-Authentifizierung zu erreichen?

WBOY
WBOYnach vorne
2023-05-18 13:19:061476Durchsuche

Einführung in JWT

JWT (vollständiger Name: Json Web Token) ist ein offener Standard (RFC 7519), der eine kompakte, eigenständige Möglichkeit zur sicheren Übertragung von Informationen zwischen Parteien als JSON-Objekt definiert.

Warum JWT verwenden?

Was sind die Nachteile der herkömmlichen Sitzungsauthentifizierung?

  • Die Anmeldeinformationen jedes Benutzers werden in der Sitzung des Servers gespeichert. Mit zunehmender Anzahl von Benutzern steigt der Serveraufwand erheblich.

  • Sitzungsinformationen werden im Speicher des Servers gespeichert, was bei verteilten Anwendungen zu Fehlern führt. Obwohl die Sitzungsinformationen einheitlich im Redis-Cache gespeichert werden können, kann dies die Komplexität erhöhen.

  • Da die Sitzungsauthentifizierung auf Cookies basiert, ist sie nicht auf Nicht-Browser- und mobile Endgeräte anwendbar.

  • Das Front-End- und Back-End-Trennsystem, da Front-End und Back-End domänenübergreifend sind und Cookie-Informationen nicht gekreuzt werden können, sodass die Sitzungsauthentifizierung die domänenübergreifende Authentifizierung nicht fortsetzen kann.

Vorteile der JWT-Authentifizierung

  • Einfach: Das Datenvolumen des JWT-Tokens ist gering und die Übertragungsgeschwindigkeit ist ebenfalls sehr hoch.

  • Sprachübergreifend: JWT-Token wird auf dem Client in JSON-verschlüsselter Form gespeichert, sodass JWT sprachübergreifend ist und von jedem Webformular unterstützt wird. Plattformübergreifend: Verlässt sich nicht auf Cookies und Sitzungen und muss keine Sitzungsinformationen auf dem Server speichern. Es eignet sich sehr gut für verteilte Anwendungen und kann zur Erweiterung verwendet werden.

Datenstruktur von JWT

Wie integriert Spring Boot JWT, um eine Front-End- und Back-End-Authentifizierung zu erreichen?

Header

Der erste Teil von JWT ist der Header-Teil, bei dem es sich um ein Json-Objekt handelt, das die JWT-Metadaten beschreibt, normalerweise wie unten gezeigt.

{
    "alg": "HS256",
    "typ": "JWT"
}

Das alg-Attribut gibt den für die Signatur verwendeten Algorithmus an, der Standardwert ist HMAC SHA256 (geschrieben als HS256), das typ-Attribut gibt den Typ des Tokens an und JWT-Tokens werden einheitlich als JWT geschrieben.

Payload

Der zweite Teil von JWT ist Payload, bei dem es sich ebenfalls um ein Json-Objekt handelt. Zusätzlich zu den zu übergebenden Daten stehen sieben Standardfelder zur Auswahl. iss: Issuer exp: Ablaufzeit sub: Subject aud: User nbf: Nicht verfügbar vor iat: Release-Zeit jti: Die JWT-ID wird verwendet, um dieses JWT zu identifizieren

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

Es ist wichtig zu beachten, dass JWT standardmäßig unverschlüsselt ist, das kann jeder Entschlüsseln Sie den Inhalt. Wenn also vertrauliche Informationen hier nicht gespeichert sind, können Sie Informationslecks verhindern. Auch JSON-Objekte werden mithilfe des Base64-URL-Algorithmus in Strings umgewandelt und gespeichert.

Signatur

Der Signatur-Hash-Teil besteht darin, die beiden oben genannten Datenteile zu signieren. Er muss Base64-codierte Header- und Nutzdaten verwenden und über den angegebenen Algorithmus einen Hash generieren, um sicherzustellen, dass die Daten nicht manipuliert werden.

Spring Boot integriert JWT

Einführung des Jwt-Pakets

<dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt</artifactId>
        <version>0.9.1</version>
  </dependency>

JWT-Toolklasse schreiben

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";
  }

Token-Authentifizierungs-Interceptor

 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;
    }

}

Konfigurations-Interceptor

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

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

Anmeldeüberprüfungsprozess

Wie integriert Spring Boot JWT, um eine Front-End- und Back-End-Authentifizierung zu erreichen?

Beispielcode

@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;
}

Das obige ist der detaillierte Inhalt vonWie integriert Spring Boot JWT, um eine Front-End- und Back-End-Authentifizierung zu erreichen?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:yisu.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen