>  기사  >  Java  >  SpringBoot에 JWT 인증을 통합하는 방법(코드 포함)

SpringBoot에 JWT 인증을 통합하는 방법(코드 포함)

不言
不言앞으로
2019-03-19 09:39:393485검색

이 기사의 내용은 SpringBoot에 JWT 인증을 통합하는 방법(코드 포함)에 대한 내용입니다. 필요한 친구가 참고할 수 있기를 바랍니다.

1. JWT에 대하여

1.1 JWT란 무엇인가

이런 도구를 사용하려면 먼저 다음 질문을 알아야 합니다.

  • 이 도구는 어떤 문제를 해결하나요?
  • 현재 비즈니스 시나리오에 적용할 수 있나요?
  • 사용 후 다른 문제가 발생하나요? it
  • 그럼 JWT란 무엇일까요? 다음은 jwt 공식 웹사이트의 JWT 소개를 제가 번역한 것입니다.

JSON 웹 토큰(JWT)은 JSON 개체를 사용하여 당사자 간에 정보를 안전하게 전송하기 위한 컴팩트하고 독립적인 방법을 정의하는 개방형 표준(RFC 7519)입니다.

이제 우리는 JWT가 실제로 여러 지점 간에 JSON으로 표시되는 데이터를 안전하게 전송하기 위한 개방형 표준이라는 것을 알고 있습니다. 전송 과정에서 JWT는 문자열 형태로 우리 시야에 나타납니다. 이 문자열의 정보는 디지털 서명을 통해 확인하고 신뢰할 수 있습니다. (추천:
Java Tutorial

)1.2 응용 시나리오

실제 개발에서 JWT의 응용 시나리오는 무엇인가요?

1.2.1 승인

이것은 JWT의 가장 일반적인 사용 시나리오로 간주되어야 합니다. 프런트엔드 인터페이스에서 사용자가 성공적으로 로그인하면 백엔드에서 반환된 JWT가 수신됩니다. 후속 요청에는 백엔드 경로, 서비스 및 리소스에 액세스하기 위한 자격 증명으로 백엔드에서 반환한 JWT가 포함됩니다.

1.2.2 정보 교환

JWT를 사용하여 여러 당사자 간에 정보를 전송하면 어느 정도 보안이 유지됩니다. 예를 들어 JWT는 HMAC, RSA 비대칭 암호화 알고리즘 및 ECDSA 디지털 서명 알고리즘을 사용하여 JWT에 서명할 수 있으므로 전송을 보장할 수 있습니다. 보낸 사람이 실제 보낸 사람이고, 헤더와 페이로드의 서명 계산을 통해 보낸 메시지가 변조되었는지 여부도 확인할 수 있습니다.

2. JWT의 구조

일반적으로 JWT는 header.payload.signature 세 부분으로 구성된 문자열입니다. 여기서 간단히 소개하겠습니다.

2.1 headerheader.payload.signature三部分组成的字符串,网上有太多帖子介绍这一块了,所以在这里就简单介绍一下就好了。

2.1 header

header由使用的签名算法和令牌的类型的组成,例如令牌的类型就是JWT这种开放标准,而使用的签名算法就是HS256,也就是HmacSHA256算法。其他的加密算法还有HmacSHA512SHA512withECDSA等等。

然后将这个包含两个属性的JSON对象转化为字符串然后使用Base64编码,最终形成了JWT的header。

2.2 payload

payload说直白一些就类似你的requestBody中的数据。只不过是分了三种类型,预先申明好的、自定义的以及私有的。像iss发件人,exp过期时间都是预先注册好的申明。

预先申明在载荷中的数据不是强制性的使用,但是官方建议使用。然后这串类似于requestBody的JSON经过Base64编码形成了JWT的第二部分。

2.3 signature

如果要生成signature,就需要使用jwt自定义配置项中的secret,也就是Hmac算法加密所需要的密钥。将之前经过Base64编码的header和payload用.相连,再使用自定义的密钥,对该消息进行签名,最终生成了签名。

生成的签名用于验证消息在传输的过程中没有被更改。在使用非对称加密算法进行签名的时候,还可以用于验证JWT的发件人是否与payload中申明的发件人是同一个人。

3.JWT在Spring项目中的应用场景

3.1 生成JWT

代码如下。

public String createJwt(String userId, String projectId) throws IllegalArgumentException, UnsupportedEncodingException {
    Algorithm al = Algorithm.HMAC256(secret);
    Instant instant = LocalDateTime.now().plusHours(outHours).atZone(ZoneId.systemDefault()).toInstant();
    Date expire = Date.from(instant);
    String token = JWT.create()
            .withIssuer(issuer)
            .withSubject("userInfo")
            .withClaim("user_id", userId)
            .withClaim("project_id", projectId)
            .withExpiresAt(expire)
            .sign(al);
    return token;
}

传入的两个Claim是项目里自定义的payload,al是选择的算法,而secret就是对信息签名的密钥,subject则是该token的主题,withExpiresAt标识了该token的过期时间。

3.2 返回JWT

在用户登录系统成功之后,将token作为返回参数,返回给前端。

3.3 验证token

在token返回给前端之后,后端要做的就是验证这个token是否是合法的,是否可以访问服务器的资源。主要可以通过以下几种方式去验证。

3.3.1 解析token

使用JWTVerifier

header는 사용되는 서명 알고리즘과 토큰 유형으로 구성됩니다. 예를 들어 토큰 유형은 JWT와 같은 개방형 표준이고 사용되는 서명 알고리즘은 입니다. HS256, 이는 <code>HmacSHA256 알고리즘입니다. 다른 암호화 알고리즘에는 HmacSHA512, SHA512withECDSA 등이 포함됩니다.

그런 다음 두 개의 속성이 포함된 이 JSON 개체를 문자열로 변환한 다음 Base64 인코딩을 사용하여 최종적으로 JWT 헤더를 형성합니다.

2.2 payload

payload 더 간단하게 말하면 requestBody의 데이터와 유사합니다. 사전 선언형, 사용자 정의 및 개인용의 세 가지 유형만 있습니다. iss 발신자와 마찬가지로 exp 만료 시간은 미리 등록된 명령문입니다.

페이로드의 데이터를 미리 선언하는 것은 필수는 아니지만 공식적으로 권장됩니다. 그런 다음 requestBody와 유사한 이 JSON 문자열은 Base64로 인코딩되어 JWT의 두 번째 부분을 구성합니다. 🎜🎜2.3 서명🎜🎜서명을 생성하려면 Hmac 알고리즘 암호화에 필요한 키인 jwt 사용자 정의 구성 항목의 비밀 키를 사용해야 합니다. 이전에 Base64로 인코딩된 헤더와 페이로드를 .로 연결한 다음 사용자 지정 키를 사용하여 메시지에 서명하고 마지막으로 서명을 생성합니다. 🎜🎜생성된 서명은 메시지가 전송 중에 변경되지 않았는지 확인하는 데 사용됩니다. 서명을 위해 비대칭 암호화 알고리즘을 사용하는 경우 JWT의 보낸 사람이 페이로드에 선언된 보낸 사람과 동일한 사람인지 확인하는 데에도 사용할 수 있습니다. 🎜🎜3. Spring 프로젝트의 JWT 적용 시나리오🎜🎜3.1 JWT🎜🎜를 생성하는 코드는 다음과 같습니다. 🎜
try {
    Algorithm algorithm = Algorithm.HMAC256(secret);
    JWTVerifier verifier = JWT.require(algorithm).build();
    DecodedJWT jwt = verifier.verify(token);
} catch (JWTVerificationException e) {
    e.printStackTrace();
}
🎜전달된 두 개의 클레임은 프로젝트의 사용자 정의 페이로드이고, al은 선택된 알고리즘이고, secret은 정보에 서명하기 위한 키입니다. 제목 는 토큰의 제목이고 withExpiresAt는 토큰의 만료 시간을 식별합니다. 🎜🎜3.2 Return JWT🎜🎜사용자가 시스템에 성공적으로 로그인한 후 토큰은 반환 매개변수로 사용되어 프런트 엔드로 반환됩니다. 🎜🎜3.3 토큰 확인🎜🎜토큰이 프런트엔드로 반환된 후 백엔드에서 해야 할 일은 토큰이 합법적인지, 서버의 리소스에 접근할 수 있는지 확인하는 것입니다. 주로 다음과 같은 방법을 통해 확인할 수 있습니다. 🎜🎜3.3.1 토큰 구문 분석🎜🎜JWTVerifier를 사용하여 토큰을 구문 분석합니다. 이는 토큰이 합법적인지 확인하는 첫 번째 단계입니다. 예를 들어 프런트 엔드에서 전달된 토큰은 다음과 같습니다. 의미 없는 문자열입니다. 여기서는 한 단계에서 오류가 발생할 수 있습니다. 샘플 코드는 다음과 같습니다. 🎜
try {
    Algorithm algorithm = Algorithm.HMAC256(secret);
    JWTVerifier verifier = JWT.require(algorithm).build();
    DecodedJWT jwt = verifier.verify(token);
    if (jwt.getExpiresAt().before(new Date())) {
        System.out.println("token已过期");
        return null;
    }
} catch (JWTVerificationException e) {
    e.printStackTrace();
    return null;
}
🎜JWTVerifier는 비밀 서명과 지정된 클레임을 공식화하는 알고리즘을 사용하여 토큰의 적법성을 확인할 수 있습니다. 🎜🎜3.3.2 토큰의 유효성 확인🎜🎜토큰이 유효한 것으로 판단한 후 토큰의 유효성을 확인합니다. 🎜rrreee🎜토큰이 만료되면 서버 리소스에 접근할 수 없습니다. 구체적인 과정은 다음과 같습니다. 🎜

SpringBoot에 JWT 인증을 통합하는 방법(코드 포함)

3.3.3 새로 고침 만료 시간

위에서 생성한 토큰의 유효 시간은 2시간으로 가정하여 구성 가능하며, 사용자가 로그인하여 1시간 59분 동안 매우 중요한 작업을 수행할 때 연속적으로 작업합니다. , 확인을 클릭하면 현재 토큰이 만료되었습니다. 프로그램에 보호 전략이 없으면 사용자 작업 중 거의 2시간이 헛된 것입니다.

이러한 문제에 직면하면 이전 프로세스 설계는 필연적으로 재구성에 직면하게 됩니다. 질문이 있을 수 있습니다. 사용자가 로그인한 후 각 작업에 대해 토큰 만료 시간을 새로 고쳐야 하지 않나요?

그러면 우리는 토큰이 header.payload.signature세 가지 콘텐츠로 구성되어 있고 만료 시간이 페이로드에 속한다는 것을 알고 있습니다. 만료 시간이 변경되면 최종 생성된 페이로드의 해시가 마지막과 달라집니다. 하나를 생성했습니다.

즉, 이것은 완전히 새로운 토큰입니다. 프런트 엔드는 이 새 토큰을 어떻게 받나요? 생각할 수 있는 해결책은 각 요청에 대한 응답 헤더의 반환을 기반으로 토큰을 지속적으로 새로 고치는 것입니다. 그러나 이 방법은 프런트엔드 개발의 비즈니스 계층을 침범합니다. 각 인터페이스는 토큰을 새로 고쳐야 합니다.

비즈니스에 크게 방해가 되지 않는 인터셉터를 추가하는 것에 지나지 않는다고 할 수도 있습니다. 로직의 이 부분이 인터셉터에 작성되어 있더라도 토큰 인증 로직으로 인해 프런트 엔드에는 이러한 추가 코드가 있습니다. 기능적 업무 분업 측면에서 보면 코드의 이 부분은 실제로 백엔드 로직입니다.

더 간단하게 말하면 토큰을 새로 고치고 토큰의 적시성을 관리하는 일은 백엔드에서 수행해야 합니다. 프런트엔드는 이 로직 부분을 필요로 하지 않으며 신경써서도 안 됩니다.

3.3.4 Redis는 좋은 방법입니다

결론적으로 새로고침 토큰의 만료 시간은 백엔드에 배치해야 하며, 토큰의 유효성 여부는 JWT의 페이로드에 있는 만료 시간으로 판단할 수 없습니다.

따라서 사용자가 성공적으로 로그인하고 토큰을 프런트 엔드에 반환한 후에는 고유한 표현을 키로, 현재 토큰을 값으로 사용하여 Redis 캐시에 기록해야 합니다. 그리고 각 사용자 요청이 성공한 후 토큰의 만료 시간이 새로 고쳐집니다.

SpringBoot에 JWT 인증을 통합하는 방법(코드 포함)

이렇게 재구성하고 나면 과정은 이렇게 됩니다.

SpringBoot에 JWT 인증을 통합하는 방법(코드 포함)

이 과정에서 토큰을 새로 고치는 추가 과정이 있습니다. 사용자가 시스템에 로그인하는 한 각 작업은 토큰의 만료 시간을 새로 고치며 앞서 언급한 작업 중 갑작스러운 실패로 인한 데이터 손실은 없습니다.

사용자가 로그인한 후 2시간 이내에 사용자가 아무런 작업도 수행하지 않은 경우, 2시간 후에 다시 인터페이스를 요청하면 서버에서 직접 액세스가 거부됩니다.

4. 요약

일반적으로 JWT에는 특히 민감한 정보를 넣는 것을 권장하지 않습니다. 비대칭 암호화 알고리즘을 사용하지 않는 경우에는 토큰을 복사한 후 jwt 공식 홈페이지에 직접 접속해 온라인으로 분석할 수 있습니다. 요청이 차단되면 내부의 모든 정보가 투명해집니다.

하지만 JWT는 일정 기간 동안 서버 리소스에 액세스하기 위한 자격 증명으로 사용될 수 있습니다. 예를 들어 JWT 페이로드에 userId 필드가 포함되어 있으면 토큰으로 식별된 사용자의 적법성을 확인할 수 있습니다. 예를 들어, 사용자가 현재 잠겨 있습니까? 이 userId로 식별된 사용자가 우리 시스템에 존재합니까? 등.

그리고 토큰을 공개함으로써 사용자는 동시에 여러 단말기에서 로그인할 수 있습니다. 이전처럼 로그인 후 토큰을 생성하면 사용자가 동시에 하나의 장치에만 로그인할 수 있도록 제한됩니다.


위 내용은 SpringBoot에 JWT 인증을 통합하는 방법(코드 포함)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 segmentfault.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제