Làm thế nào để giải mã JWT Token?


101

Tôi không hiểu thư viện này hoạt động như thế nào. Bạn có thể vui lòng giúp tôi không ?

Đây là mã đơn giản của tôi:

public void TestJwtSecurityTokenHandler()
    {
        var stream =
            "eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJJU1MiLCJzY29wZSI6Imh0dHBzOi8vbGFyaW0uZG5zY2UuZG91YW5lL2NpZWxzZXJ2aWNlL3dzIiwiYXVkIjoiaHR0cHM6Ly9kb3VhbmUuZmluYW5jZXMuZ291di5mci9vYXV0aDIvdjEiLCJpYXQiOiJcL0RhdGUoMTQ2ODM2MjU5Mzc4NClcLyJ9";
        var handler = new JwtSecurityTokenHandler();

        var jsonToken = handler.ReadToken(stream);
    }

Đây là lỗi:

Chuỗi cần phải có định dạng JSON nhỏ gọn, có dạng: Base64UrlEncodedHeader.Base64UrlEndcodedPayload.OPTIONAL, Base64UrlEncodedSignature '.

Nếu bạn sao chép luồng trong trang web jwt.io , nó hoạt động tốt :)


1
trang jwt, io giải mã được nhưng không có chữ ký nên không hợp lệ.
Crowcoder


1
@MichaelFreidgeim bạn nói đúng đó là trùng lặp câu hỏi ... nhưng câu trả lời là khác nhau vì thư viện phiên bản bạn sử dụng
Cooxkie

Câu trả lời:


175

Tôi đã tìm thấy giải pháp, tôi chỉ quên Truyền kết quả:

var stream ="[encoded jwt]";  
var handler = new JwtSecurityTokenHandler();
var jsonToken = handler.ReadToken(stream);
var tokenS = handler.ReadToken(stream) as JwtSecurityToken;

Tôi có thể nhận được Yêu cầu bằng cách sử dụng:

var jti = tokenS.Claims.First(claim => claim.Type == "jti").Value;

2
Trước tiên, tôi phải chuyển tokenS.Các yêu cầu dưới dạng Danh sách Yêu cầu. ((List<Claim>)tokenS.Claims).ForEach(a => Console.WriteLine(a.Type.ToString() + " " + a.Value));
Rinaldi Segecin

12
Bạn cũng có thể thực hiện: handler.ReadJwtToken (tokenJwtReponse.access_token);
Thabiso Mofokeng

13
Xin lỗi nếu điều này nên rõ ràng nhưng tokenJwtReponse.access_tokenđến từ đâu?
Jeff Stapleton

3
TokenJwtReponse.access_token đến từ đâu?
3iL

4
Như những người khác đã đặt câu hỏi: "tokenJwtReponse.access_token" đến từ đâu? Không có định nghĩa hoặc tuyên bố cho nó trong câu trả lời, làm cho câu trả lời trở nên vô nghĩa và vô nghĩa đối với nhiều người trong chúng ta.
Zeek2

33

new JwtSecurityTokenHandler().ReadToken("") sẽ trả lại một SecurityToken

new JwtSecurityTokenHandler().ReadJwtToken("") sẽ trả lại một JwtSecurityToken

Nếu bạn chỉ thay đổi phương pháp bạn đang sử dụng, bạn có thể tránh được phép cast trong câu trả lời trên


16

Bạn cần chuỗi bí mật được sử dụng để tạo mã thông báo mã hóa. Mã này phù hợp với tôi:

protected string GetName(string token)
    {
        string secret = "this is a string used for encrypt and decrypt token"; 
        var key = Encoding.ASCII.GetBytes(secret);
        var handler = new JwtSecurityTokenHandler();
        var validations = new TokenValidationParameters
        {
            ValidateIssuerSigningKey = true,
            IssuerSigningKey = new SymmetricSecurityKey(key),
            ValidateIssuer = false,
            ValidateAudience = false
        };
        var claims = handler.ValidateToken(token, validations, out var tokenSecure);
        return claims.Identity.Name;
    }

Tại sao bạn lại gọi handler.ReadToken(token) as SecurityTokenkhi bạn đang gán lại nó làm outtham số của mình sau này? Có khả năng ValidateTokenkhông thành công và giá trị ban đầu được giữ?
krillgar

Right krillgar không cần đến dàn diễn viên cho SecurityToken
Pato Milán

ValidateToken có kiểm tra thời hạn không? Hay tôi cần phải tự xác thực điều đó sau khi nó được giải mã?
computrius

9

Sử dụng các gói jwt lõi .net, các Tuyên bố có sẵn:

[Route("api/[controller]")]
[ApiController]
[Authorize(Policy = "Bearer")]
public class AbstractController: ControllerBase
{
    protected string UserId()
    {
        var principal = HttpContext.User;
        if (principal?.Claims != null)
        {
            foreach (var claim in principal.Claims)
            {
               log.Debug($"CLAIM TYPE: {claim.Type}; CLAIM VALUE: {claim.Value}");
            }

        }
        return principal?.Claims?.SingleOrDefault(p => p.Type == "username")?.Value;
    }
}

6
  var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"]));
        var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
        var claims = new[]
                {
                    new Claim(JwtRegisteredClaimNames.Email, model.UserName),
                    new Claim(JwtRegisteredClaimNames.NameId, model.Id.ToString()),
                };
        var token = new JwtSecurityToken(_config["Jwt:Issuer"],
          _config["Jwt:Issuer"],
          claims,
          expires: DateTime.Now.AddMinutes(30),
          signingCredentials: creds);

Sau đó trích xuất nội dung

 var handler = new JwtSecurityTokenHandler();
        string authHeader = Request.Headers["Authorization"];
        authHeader = authHeader.Replace("Bearer ", "");
        var jsonToken = handler.ReadToken(authHeader);
        var tokenS = handler.ReadToken(authHeader) as JwtSecurityToken;

        var id = tokenS.Claims.First(claim => claim.Type == "nameid").Value;

3

Mở rộng trên câu trả lời cooxkie và câu trả lời dpix , khi bạn đang đọc mã thông báo jwt (chẳng hạn như access_token nhận được từ AD FS), bạn có thể hợp nhất các xác nhận quyền sở hữu trong mã thông báo jwt với các xác nhận quyền sở hữu từ "context.AuthenticationTicket.Identity" mà có thể không có cùng một tập hợp xác nhận quyền sở hữu như mã thông báo jwt.

Để minh họa, trong luồng Mã xác thực sử dụng OpenID Connect, sau khi người dùng được xác thực, bạn có thể xử lý sự kiện SecurityTokenValidated cung cấp cho bạn bối cảnh xác thực, sau đó bạn có thể sử dụng nó để đọc access_token dưới dạng mã thông báo jwt, sau đó bạn có thể " hợp nhất "mã thông báo trong access_token với danh sách tiêu chuẩn của các yêu cầu nhận được như một phần của danh tính người dùng:

    private Task OnSecurityTokenValidated(SecurityTokenValidatedNotification<OpenIdConnectMessage,OpenIdConnectAuthenticationOptions> context)
    {
        //get the current user identity
        ClaimsIdentity claimsIdentity = (ClaimsIdentity)context.AuthenticationTicket.Identity;

        /*read access token from the current context*/
        string access_token = context.ProtocolMessage.AccessToken;

        JwtSecurityTokenHandler hand = new JwtSecurityTokenHandler();
        //read the token as recommended by Coxkie and dpix
        var tokenS = hand.ReadJwtToken(access_token);
        //here, you read the claims from the access token which might have 
        //additional claims needed by your application
        foreach (var claim in tokenS.Claims)
        {
            if (!claimsIdentity.HasClaim(claim.Type, claim.Value))
                claimsIdentity.AddClaim(claim);
        }

        return Task.FromResult(0);
    }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.