> Java > java지도 시간 > Spring Boot는 프런트엔드 및 백엔드 인증을 달성하기 위해 JWT를 어떻게 통합합니까?

Spring Boot는 프런트엔드 및 백엔드 인증을 달성하기 위해 JWT를 어떻게 통합합니까?

WBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWB
풀어 주다: 2023-05-18 13:19:06
앞으로
1637명이 탐색했습니다.

JWT 소개

JWT(전체 이름: Json Web Token)는 당사자 간에 정보를 JSON 개체로 안전하게 전송하는 간결하고 독립적인 방법을 정의하는 개방형 표준(RFC 7519)입니다.

JWT를 사용하는 이유

기존 세션 인증의 단점은 무엇인가요?

  • 각 사용자의 로그인 정보는 서버의 세션에 저장되며, 사용자 수가 늘어날수록 서버 오버헤드가 크게 늘어납니다.

  • 세션 정보는 서버의 메모리에 저장되므로 분산 애플리케이션에 오류가 발생할 수 있습니다. 세션 정보가 Redis 캐시에 균일하게 저장될 수 있지만 이로 인해 복잡성이 증가할 수 있습니다.

  • 세션 인증은 쿠키 기반이므로 비 브라우저 및 모바일 단말에서는 적용되지 않습니다.

  • 프런트엔드와 백엔드 분리 시스템은 프런트엔드와 백엔드가 크로스 도메인이고, 쿠키 정보를 교차할 수 없기 때문에 세션 인증이 크로스 도메인 인증을 이어갈 수 없기 때문입니다.

JWT 인증의 장점

  • 간단함: JWT 토큰의 데이터 양은 적고 전송 속도도 매우 빠릅니다.

  • 교차 언어: JWT 토큰은 JSON 암호화 형식으로 클라이언트에 저장되므로 JWT는 언어 간이며 모든 웹 양식에서 지원됩니다. 크로스 플랫폼: 쿠키와 세션에 의존하지 않으며 서버에 세션 정보를 저장할 필요가 없으며 분산 애플리케이션에 매우 적합하며 확장에 사용할 수 있습니다.

JWT의 데이터 구조

Spring Boot는 프런트엔드 및 백엔드 인증을 달성하기 위해 JWT를 어떻게 통합합니까?

Header

JWT의 첫 번째 부분은 일반적으로 아래와 같이 JWT 메타데이터를 설명하는 Json 객체인 헤더 부분입니다.

1

2

3

4

{

    "alg": "HS256",

    "typ": "JWT"

}

로그인 후 복사

alg 속성은 서명에 사용되는 알고리즘을 나타내며, 기본값은 HMAC SHA256(HS256으로 작성됨)이고, typ 속성은 토큰 유형을 나타내며, JWT 토큰은 JWT로 일률적으로 작성됩니다.

Payload

JWT의 두 번째 부분은 Json 객체이기도 한 Payload입니다. 전달해야 하는 데이터를 포함하는 것 외에도 선택할 수 있는 7개의 기본 필드가 있습니다. iss: 발행자 exp: 만료 시간 sub: 제목 aud: 사용자 nbf: 이전에는 사용할 수 없음 iat: 릴리스 시간 jti: JWT ID는 이 JWT를 식별하는 데 사용됩니다

1

2

3

4

5

6

7

8

{

    //默认字段

    "sub":"主题123",

    //自定义字段

    "name":"java",

    "isAdmin":"true",

    "loginTime":"2021-12-05 12:00:03"

}

로그인 후 복사

JWT는 기본적으로 암호화되지 않는다는 점에 유의하는 것이 중요합니다. 내용을 해독하므로 일부 민감한 정보가 여기에 저장되지 않은 경우 정보 유출을 방지할 수 있습니다. JSON 객체도 Base64 URL 알고리즘을 사용하여 문자열로 변환되어 저장됩니다.

Signature

서명 해시 부분은 위 두 부분의 데이터에 서명하는 것으로, base64로 인코딩된 헤더와 페이로드 데이터를 사용해야 하며, 데이터가 변조되지 않도록 지정된 알고리즘을 통해 해시를 생성해야 합니다.

Spring Boot는 JWT를 통합합니다

Jwt 패키지 소개

1

2

3

4

5

<dependency>

        <groupId>io.jsonwebtoken</groupId>

        <artifactId>jjwt</artifactId>

        <version>0.9.1</version>

  </dependency>

로그인 후 복사

jwt 도구 클래스 작성

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

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

  }

로그인 후 복사

토큰 인증 인터셉터

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

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;

    }

 

}

로그인 후 복사

구성 인터셉터

1

2

3

4

5

6

7

8

9

10

11

@Configuration

public class WebConfig implements WebMvcConfigurer

{

    @Resource

    private TokenInterceptor tokenInterceptor;

 

    public void addInterceptors(InterceptorRegistry registry)

    {

        registry.addInterceptor(tokenInterceptor).addPathPatterns("/**");

    }

 }

로그인 후 복사

로그인 확인 프로세스

Spring Boot는 프런트엔드 및 백엔드 인증을 달성하기 위해 JWT를 어떻게 통합합니까?

샘플 코드

아아아아

위 내용은 Spring Boot는 프런트엔드 및 백엔드 인증을 달성하기 위해 JWT를 어떻게 통합합니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿