JWTワンポイントログイン


JWTの紹介:
JWT、すなわちJSON Web Token(JWT)は、現在最も流行しているドメイン間認証ソリューションです.
JWTの構成:
JWTは実際には文字列であり、頭部(Header)、荷重(Payload)、署名(signature)の3つの部分から構成されている.
1, Header
{“typ”:“JWT”,“alg”:“HS256”}
このjsonのtypプロパティは、token文字列全体がJWT文字列であることを識別するために使用されます.そのalg属性は、このJWTの発行時に使用される署名と要約アルゴリズムを説明するために使用されます.
typとalg属性の全称は実はtypeとalgorithmで、それぞれタイプとアルゴリズムの意味です.3文字で表すのも、JWTの最終文字列の大きさを考慮したものです.
JWTという名前と一致しているので、3文字になります...typとalgはJWTで標準的に規定されている属性名です
2,Payload(負荷)
{“sub”:“123”,“name”:“Tom”,“admin”:true}
payloadは、JWT規格でclaimsと呼ばれているJWTによって伝達されるデータのセットであるjson構造の宣言を搬送するために使用されます.
プロパティ値ペアはclaim(要件)です.
各claimは、特定の意味と役割を表します.
3 signature
署名はヘッダとpayloadに対応するjson構造をbase 64 url符号化して得られた2つの列を英語の句点番号でつなぎ合わせ,ヘッダにalgが指定した署名アルゴリズムに基づいて生成する.
アルゴリズムが異なり、署名結果が異なります.alg:HS 256を例に、前の署名がどのように得られるかを説明します.
前述のalg利用可能な値の説明によれば、HS 256は、要約を生成するために使用されるHMACアルゴリズムとSHA 256アルゴリズムの2つのアルゴリズム、および要約をデジタル署名するために使用されるSHA 256アルゴリズムを含む.この2つのアルゴリズムはHMACSHA 256で総称することもできる.
JWTの検証プロセス
JWT検証の方法は実は簡単で、headerをbase 64 urlで復号すれば、JWTがどんなアルゴリズムで作った署名を知って、このアルゴリズムで、headerとpayloadに再び同じ論理で署名することができます.
この署名がJWT自体に含まれる3番目の部分の列と完全に同じかどうかを比較し、異なる限り、このJWTは改ざんされた列であると考えられ、当然検証に失敗した.
受信者が署名を生成するときは、JWT送信者と同じ鍵を使用する必要があります.
JWT結合springbootプロジェクト:
  • pom.xml追加は、
     
     
     	com.auth0
     	java-jwt
     	3.8.1
     
     
     
     	io.jsonwebtoken
     	jjwt
     	0.9.1
     
    
  • testユニットテスト暗号化
     @Test
     public void testCase1(){
     	JwtBuilder builder = Jwts.builder();
     	JwtBuilder jwtBuilder = builder.setSubject("yangjingwen")
     		.signWith(SignatureAlgorithm.HS256, "qianfeng")
     		.claim("role", "admin")
     		.setExpiration(new Date(System.currentTimeMillis() + 60000))
     		.setIssuedAt(new Date());
     	String compact = jwtBuilder.compact();
     	System.out.println(compact);
     }
    
  • testユニットテスト復号
     @Test
     public void testCase2(){
     	String 	token="eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ5YW5namluZ3dlbiIsInJvbGUiOiJhZG1pbiIsI	mV4cCI6MTU2MzI2ODUzNywiaWF0IjoxNTYzMjY4NDc3fQ.mHrESLyGONzlAXwOmRa	U3gkVwFZ_pNqBUl7WcM2vviE";
     	String key="qianfeng";
     	Claims body = Jwts.parser().setSigningKey(key)
     			.parseClaimsJws(token).getBody();
     	String subject = body.getSubject();
     	Date issuedAt = body.getIssuedAt();
     	Date expiration = body.getExpiration();
     }
    
  • JWT基本使用
    tokenを生成するロジック:ログインに成功した後、jwtを使用してtokenを生成します.
    //      ,    token
    String token = Jwts.builder().setSubject(userDTO.getUsername()) //  ,          
        .setIssuedAt(new Date()) //token    
        .setExpiration(new Date(System.currentTimeMillis() + 60000)) //token    
        .setId(memeber.getMemeberId()) //  ID
        .setClaims(hashMap) //      
        .signWith(SignatureAlgorithm.HS256, "qianfeng") //         
        .compact();
    

    Token検査
    try {
        JwtParser parser = Jwts.parser();
        parser.setSigningKey("qianfeng");
        Jws claimsJws = parser.parseClaimsJws(token);
        Claims body = claimsJws.getBody();
        String username = body.getSubject();
        Object role = body.get("role");
        return true;
    } catch (ExpiredJwtException e) {
    	e.printStackTrace();
    } catch (UnsupportedJwtException e) {
        e.printStackTrace();
    } catch (MalformedJwtException e) {
    	e.printStackTrace();
    } catch (SignatureException e) {
    	e.printStackTrace();
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    }
    

    Springbootブロッキングのオン方法
    package com.qianfeng.interceptor;
    
    import io.jsonwebtoken.*;
    import org.springframework.stereotype.Component;
    import org.springframework.web.servlet.HandlerInterceptor;
    import org.springframework.web.servlet.ModelAndView;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    /**
     *     
     */
    @Component
    public class LoginInterceptor implements HandlerInterceptor {
    
      	@Override
    	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String token = request.getParameter("token");
    
        try {
            JwtParser parser = Jwts.parser();
            parser.setSigningKey("qianfeng");
            Jws claimsJws = parser.parseClaimsJws(token);
            Claims body = claimsJws.getBody();
            String username = body.getSubject();
            Object role = body.get("role");
    
            return true;
        } catch (ExpiredJwtException e) {
            e.printStackTrace();
        } catch (UnsupportedJwtException e) {
            e.printStackTrace();
        } catch (MalformedJwtException e) {
            e.printStackTrace();
        } catch (SignatureException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        }
    
    
        return false;
      }
    
     	 @Override
       public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    
        }
    
       @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse 	response, Object handler, Exception ex) throws Exception {
    
        }
    }
    

    ブロッキングを追加
    package com.qianfeng.configuration;
    
    import com.qianfeng.interceptor.LoginInterceptor;
    import org.springframework.cloud.client.loadbalancer.LoadBalanced;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.client.RestTemplate;
    import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    
    import javax.annotation.Resource;
    
    @Configuration
    public class AppConfiguration implements WebMvcConfigurer {
    
    	@Resource
        private LoginInterceptor loginInterceptor;
    
    	@Bean
    	@LoadBalanced
    	public RestTemplate provideRestTemplate(){
        	return new RestTemplate();
    	}
    
     	/**
     	*      
     	* @param registry
    	 */
    	@Override
    	public void addInterceptors(InterceptorRegistry registry) {
    
        	registry.addInterceptor(loginInterceptor).addPathPatterns("/**");
    
        }
    }