JwtSecurityToken

代表一个jwt token,可以直接用此对象生成token字符串,也可以使用token字符串创建此对象

SecurityToken

JwtSecurityToken的基类,包含基础数据

JwtSecurityTokenHandler

创建、校验token,返回ClaimsPrincipal
  CanReadToken():确定字符串是否是格式良好的Json Web令牌(JWT)
  ReadJwtToken(string token):token字符串转为JwtSecurityToken对象
  ValidateToken(string token、TokenValidationParameters parameter,out SecurityToken validatedToken):校验token,返回ClaimsIdentity,

SymmetricSecurityKey、RsaSecurityKey

  • SymmetricSecurityKey:对称签名密钥
  • RsaSecurityKey:Rsa签名密钥,也就是私钥(非对称)

Claim标准Type

ClaimTypes

点击查看代码
public static class ClaimTypes
    {
        //
        // 摘要:
        //     The URI for a claim that specifies the actor, http://schemas.xmlsoap.org/ws/2009/09/identity/claims/actor.
        public const string Actor = "http://schemas.xmlsoap.org/ws/2009/09/identity/claims/actor";

        //
        // 摘要:
        //     The URI for a claim that specifies the anonymous user; http://schemas.xmlsoap.org/ws/2005/05/identity/claims/anonymous.
        public const string Anonymous = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/anonymous";

        //
        // 摘要:
        //     The URI for a claim that specifies details about whether an identity is authenticated,
        //     http://schemas.xmlsoap.org/ws/2005/05/identity/claims/authenticated.
        public const string Authentication = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/authentication";

        //
        // 摘要:
        //     The URI for a claim that specifies the instant at which an entity was authenticated;
        //     http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationinstant.
        public const string AuthenticationInstant = "http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationinstant";

        //
        // 摘要:
        //     The URI for a claim that specifies the method with which an entity was authenticated;
        //     http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod.
        public const string AuthenticationMethod = "http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod";

        //
        // 摘要:
        //     The URI for a claim that specifies an authorization decision on an entity; http://schemas.xmlsoap.org/ws/2005/05/identity/claims/authorizationdecision.
        public const string AuthorizationDecision = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/authorizationdecision";

        //
        // 摘要:
        //     The URI for a claim that specifies the cookie path; http://schemas.microsoft.com/ws/2008/06/identity/claims/cookiepath.
        public const string CookiePath = "http://schemas.microsoft.com/ws/2008/06/identity/claims/cookiepath";

        //
        // 摘要:
        //     The URI for a claim that specifies the country/region in which an entity resides,
        //     http://schemas.xmlsoap.org/ws/2005/05/identity/claims/country.
        public const string Country = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/country";

        //
        // 摘要:
        //     The URI for a claim that specifies the date of birth of an entity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/dateofbirth.
        public const string DateOfBirth = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/dateofbirth";

        //
        // 摘要:
        //     The URI for a claim that specifies the deny-only primary group SID on an entity;
        //     http://schemas.microsoft.com/ws/2008/06/identity/claims/denyonlyprimarygroupsid.
        //     A deny-only SID denies the specified entity to a securable object.
        public const string DenyOnlyPrimaryGroupSid = "http://schemas.microsoft.com/ws/2008/06/identity/claims/denyonlyprimarygroupsid";

        //
        // 摘要:
        //     The URI for a claim that specifies the deny-only primary SID on an entity; http://schemas.microsoft.com/ws/2008/06/identity/claims/denyonlyprimarysid.
        //     A deny-only SID denies the specified entity to a securable object.
        public const string DenyOnlyPrimarySid = "http://schemas.microsoft.com/ws/2008/06/identity/claims/denyonlyprimarysid";

        //
        // 摘要:
        //     The URI for a claim that specifies a deny-only security identifier (SID) for
        //     an entity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/denyonlysid.
        //     A deny-only SID denies the specified entity to a securable object.
        public const string DenyOnlySid = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/denyonlysid";

        //
        // 摘要:
        //     The URI for a claim that specifies the Windows deny-only group SID of the device,
        //     http://schemas.microsoft.com/ws/2008/06/identity/claims/denyonlywindowsdevicegroup.
        public const string DenyOnlyWindowsDeviceGroup = "http://schemas.microsoft.com/ws/2008/06/identity/claims/denyonlywindowsdevicegroup";

        //
        // 摘要:
        //     The URI for a claim that specifies the DNS name associated with the computer
        //     name or with the alternative name of either the subject or issuer of an X.509
        //     certificate, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/dns.
        public const string Dns = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/dns";

        //
        // 摘要:
        //     http://schemas.microsoft.com/ws/2008/06/identity/claims/dsa.
        public const string Dsa = "http://schemas.microsoft.com/ws/2008/06/identity/claims/dsa";

        //
        // 摘要:
        //     The URI for a claim that specifies the email address of an entity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress.
        public const string Email = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress";

        //
        // 摘要:
        //     http://schemas.microsoft.com/ws/2008/06/identity/claims/expiration.
        public const string Expiration = "http://schemas.microsoft.com/ws/2008/06/identity/claims/expiration";

        //
        // 摘要:
        //     http://schemas.microsoft.com/ws/2008/06/identity/claims/expired.
        public const string Expired = "http://schemas.microsoft.com/ws/2008/06/identity/claims/expired";

        //
        // 摘要:
        //     The URI for a claim that specifies the gender of an entity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/gender.
        public const string Gender = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/gender";

        //
        // 摘要:
        //     The URI for a claim that specifies the given name of an entity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname.
        public const string GivenName = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname";

        //
        // 摘要:
        //     The URI for a claim that specifies the SID for the group of an entity, http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid.
        public const string GroupSid = "http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid";

        //
        // 摘要:
        //     The URI for a claim that specifies a hash value, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/hash.
        public const string Hash = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/hash";

        //
        // 摘要:
        //     The URI for a claim that specifies the home phone number of an entity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/homephone.
        public const string HomePhone = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/homephone";

        //
        // 摘要:
        //     http://schemas.microsoft.com/ws/2008/06/identity/claims/ispersistent.
        public const string IsPersistent = "http://schemas.microsoft.com/ws/2008/06/identity/claims/ispersistent";

        //
        // 摘要:
        //     The URI for a claim that specifies the locale in which an entity resides, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/locality.
        public const string Locality = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/locality";

        //
        // 摘要:
        //     The URI for a claim that specifies the mobile phone number of an entity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/mobilephone.
        public const string MobilePhone = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/mobilephone";

        //
        // 摘要:
        //     The URI for a claim that specifies the name of an entity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name.
        public const string Name = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name";

        //
        // 摘要:
        //     The URI for a claim that specifies the name of an entity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier.
        public const string NameIdentifier = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier";

        //
        // 摘要:
        //     The URI for a claim that specifies the alternative phone number of an entity,
        //     http://schemas.xmlsoap.org/ws/2005/05/identity/claims/otherphone.
        public const string OtherPhone = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/otherphone";

        //
        // 摘要:
        //     The URI for a claim that specifies the postal code of an entity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/postalcode.
        public const string PostalCode = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/postalcode";

        //
        // 摘要:
        //     The URI for a claim that specifies the primary group SID of an entity, http://schemas.microsoft.com/ws/2008/06/identity/claims/primarygroupsid.
        public const string PrimaryGroupSid = "http://schemas.microsoft.com/ws/2008/06/identity/claims/primarygroupsid";

        //
        // 摘要:
        //     The URI for a claim that specifies the primary SID of an entity, http://schemas.microsoft.com/ws/2008/06/identity/claims/primarysid.
        public const string PrimarySid = "http://schemas.microsoft.com/ws/2008/06/identity/claims/primarysid";

        //
        // 摘要:
        //     The URI for a claim that specifies the role of an entity, http://schemas.microsoft.com/ws/2008/06/identity/claims/role.
        public const string Role = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role";

        //
        // 摘要:
        //     The URI for a claim that specifies an RSA key, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/rsa.
        public const string Rsa = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/rsa";

        //
        // 摘要:
        //     The URI for a claim that specifies a serial number, http://schemas.microsoft.com/ws/2008/06/identity/claims/serialnumber.
        public const string SerialNumber = "http://schemas.microsoft.com/ws/2008/06/identity/claims/serialnumber";

        //
        // 摘要:
        //     The URI for a claim that specifies a security identifier (SID), http://schemas.xmlsoap.org/ws/2005/05/identity/claims/sid.
        public const string Sid = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/sid";

        //
        // 摘要:
        //     The URI for a claim that specifies a service principal name (SPN) claim, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/spn.
        public const string Spn = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/spn";

        //
        // 摘要:
        //     The URI for a claim that specifies the state or province in which an entity resides,
        //     http://schemas.xmlsoap.org/ws/2005/05/identity/claims/stateorprovince.
        public const string StateOrProvince = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/stateorprovince";

        //
        // 摘要:
        //     The URI for a claim that specifies the street address of an entity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/streetaddress.
        public const string StreetAddress = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/streetaddress";

        //
        // 摘要:
        //     The URI for a claim that specifies the surname of an entity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname.
        public const string Surname = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname";

        //
        // 摘要:
        //     The URI for a claim that identifies the system entity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/system.
        public const string System = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/system";

        //
        // 摘要:
        //     The URI for a claim that specifies a thumbprint, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/thumbprint.
        //     A thumbprint is a globally unique SHA-1 hash of an X.509 certificate.
        public const string Thumbprint = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/thumbprint";

        //
        // 摘要:
        //     The URI for a claim that specifies a user principal name (UPN), http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn.
        public const string Upn = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn";

        //
        // 摘要:
        //     The URI for a claim that specifies a URI, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/uri.
        public const string Uri = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/uri";

        //
        // 摘要:
        //     The URI for a claim that specifies the user data, http://schemas.microsoft.com/ws/2008/06/identity/claims/userdata.
        public const string UserData = "http://schemas.microsoft.com/ws/2008/06/identity/claims/userdata";

        //
        // 摘要:
        //     The URI for a claim that specifies the version, http://schemas.microsoft.com/ws/2008/06/identity/claims/version.
        public const string Version = "http://schemas.microsoft.com/ws/2008/06/identity/claims/version";

        //
        // 摘要:
        //     The URI for a claim that specifies the webpage of an entity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/webpage.
        public const string Webpage = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/webpage";

        //
        // 摘要:
        //     The URI for a claim that specifies the Windows domain account name of an entity,
        //     http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname.
        public const string WindowsAccountName = "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname";

        //
        // 摘要:
        //     http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsdeviceclaim.
        public const string WindowsDeviceClaim = "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsdeviceclaim";

        //
        // 摘要:
        //     The URI for a claim that specifies the Windows group SID of the device, http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsdevicegroup.
        public const string WindowsDeviceGroup = "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsdevicegroup";

        //
        // 摘要:
        //     http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsfqbnversion.
        public const string WindowsFqbnVersion = "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsfqbnversion";

        //
        // 摘要:
        //     http://schemas.microsoft.com/ws/2008/06/identity/claims/windowssubauthority.
        public const string WindowsSubAuthority = "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowssubauthority";

        //
        // 摘要:
        //     http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsuserclaim.
        public const string WindowsUserClaim = "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsuserclaim";

        //
        // 摘要:
        //     The URI for an X.500 distinguished name claim, such as the subject of an X.509
        //     Public Key Certificate or an entry identifier in a directory services Directory
        //     Information Tree; http://schemas.xmlsoap.org/ws/2005/05/identity/claims/x500distinguishedname.
        public const string X500DistinguishedName = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/x500distinguishedname";
    }

JwtClaimTypes(推荐,简短)

如果要使用JwtClaimTypes,记得调用以下代码,确保ClaimType不被更改,不使用Map映射

JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
点击查看代码
public static class JwtClaimTypes
{
    /// <summary>Unique Identifier for the End-User at the Issuer.</summary>
    public const string Subject = "sub";

    /// <summary>End-User's full name in displayable form including all name parts, possibly including titles and suffixes, ordered according to the End-User's locale and preferences.</summary>
    public const string Name = "name";

    /// <summary>Given name(s) or first name(s) of the End-User. Note that in some cultures, people can have multiple given names; all can be present, with the names being separated by space characters.</summary>
    public const string GivenName = "given_name";

    /// <summary>Surname(s) or last name(s) of the End-User. Note that in some cultures, people can have multiple family names or no family name; all can be present, with the names being separated by space characters.</summary>
    public const string FamilyName = "family_name";

    /// <summary>Middle name(s) of the End-User. Note that in some cultures, people can have multiple middle names; all can be present, with the names being separated by space characters. Also note that in some cultures, middle names are not used.</summary>
    public const string MiddleName = "middle_name";

    /// <summary>Casual name of the End-User that may or may not be the same as the given_name. For instance, a nickname value of Mike might be returned alongside a given_name value of Michael.</summary>
    public const string NickName = "nickname";

    /// <summary>Shorthand name by which the End-User wishes to be referred to at the RP, such as janedoe or j.doe. This value MAY be any valid JSON string including special characters such as @, /, or whitespace. The relying party MUST NOT rely upon this value being unique</summary>
    /// <remarks>The RP MUST NOT rely upon this value being unique, as discussed in http://openid.net/specs/openid-connect-basic-1_0-32.html#ClaimStability </remarks>
    public const string PreferredUserName = "preferred_username";

    /// <summary>URL of the End-User's profile page. The contents of this Web page SHOULD be about the End-User.</summary>
    public const string Profile = "profile";

    /// <summary>URL of the End-User's profile picture. This URL MUST refer to an image file (for example, a PNG, JPEG, or GIF image file), rather than to a Web page containing an image.</summary>
    /// <remarks>Note that this URL SHOULD specifically reference a profile photo of the End-User suitable for displaying when describing the End-User, rather than an arbitrary photo taken by the End-User.</remarks>
    public const string Picture = "picture";

    /// <summary>URL of the End-User's Web page or blog. This Web page SHOULD contain information published by the End-User or an organization that the End-User is affiliated with.</summary>
    public const string WebSite = "website";

    /// <summary>End-User's preferred e-mail address. Its value MUST conform to the RFC 5322 [RFC5322] addr-spec syntax. The relying party MUST NOT rely upon this value being unique</summary>
    public const string Email = "email";

    /// <summary>"true" if the End-User's e-mail address has been verified; otherwise "false".</summary>
    ///  <remarks>When this Claim Value is "true", this means that the OP took affirmative steps to ensure that this e-mail address was controlled by the End-User at the time the verification was performed. The means by which an e-mail address is verified is context-specific, and dependent upon the trust framework or contractual agreements within which the parties are operating.</remarks>
    public const string EmailVerified = "email_verified";

    /// <summary>End-User's gender. Values defined by this specification are "female" and "male". Other values MAY be used when neither of the defined values are applicable.</summary>
    public const string Gender = "gender";

    /// <summary>End-User's birthday, represented as an ISO 8601:2004 [ISO8601‑2004] YYYY-MM-DD format. The year MAY be 0000, indicating that it is omitted. To represent only the year, YYYY format is allowed. Note that depending on the underlying platform's date related function, providing just year can result in varying month and day, so the implementers need to take this factor into account to correctly process the dates.</summary>
    public const string BirthDate = "birthdate";

    /// <summary>String from the time zone database (http://www.twinsun.com/tz/tz-link.htm) representing the End-User's time zone. For example, Europe/Paris or America/Los_Angeles.</summary>
    public const string ZoneInfo = "zoneinfo";

    /// <summary>End-User's locale, represented as a BCP47 [RFC5646] language tag. This is typically an ISO 639-1 Alpha-2 [ISO639‑1] language code in lowercase and an ISO 3166-1 Alpha-2 [ISO3166‑1] country code in uppercase, separated by a dash. For example, en-US or fr-CA. As a compatibility note, some implementations have used an underscore as the separator rather than a dash, for example, en_US; Relying Parties MAY choose to accept this locale syntax as well.</summary>
    public const string Locale = "locale";

    /// <summary>End-User's preferred telephone number. E.164 (https://www.itu.int/rec/T-REC-E.164/e) is RECOMMENDED as the format of this Claim, for example, +1 (425) 555-1212 or +56 (2) 687 2400. If the phone number contains an extension, it is RECOMMENDED that the extension be represented using the RFC 3966 [RFC3966] extension syntax, for example, +1 (604) 555-1234;ext=5678.</summary>
    public const string PhoneNumber = "phone_number";

    /// <summary>True if the End-User's phone number has been verified; otherwise false. When this Claim Value is true, this means that the OP took affirmative steps to ensure that this phone number was controlled by the End-User at the time the verification was performed.</summary>
    /// <remarks>The means by which a phone number is verified is context-specific, and dependent upon the trust framework or contractual agreements within which the parties are operating. When true, the phone_number Claim MUST be in E.164 format and any extensions MUST be represented in RFC 3966 format.</remarks>
    public const string PhoneNumberVerified = "phone_number_verified";

    /// <summary>End-User's preferred postal address. The value of the address member is a JSON structure containing some or all of the members defined in http://openid.net/specs/openid-connect-basic-1_0-32.html#AddressClaim </summary>
    public const string Address = "address";

    /// <summary>Audience(s) that this ID Token is intended for. It MUST contain the OAuth 2.0 client_id of the Relying Party as an audience value. It MAY also contain identifiers for other audiences. In the general case, the aud value is an array of case sensitive strings. In the common special case when there is one audience, the aud value MAY be a single case sensitive string.</summary>
    public const string Audience = "aud";

    /// <summary>Issuer Identifier for the Issuer of the response. The iss value is a case sensitive URL using the https scheme that contains scheme, host, and optionally, port number and path components and no query or fragment components.</summary>
    public const string Issuer = "iss";

    /// <summary>The time before which the JWT MUST NOT be accepted for processing, specified as the number of seconds from 1970-01-01T0:0:0Z</summary>
    public const string NotBefore = "nbf";

    /// <summary>The exp (expiration time) claim identifies the expiration time on or after which the token MUST NOT be accepted for processing, specified as the number of seconds from 1970-01-01T0:0:0Z</summary>
    public const string Expiration = "exp";

    /// <summary>Time the End-User's information was last updated. Its value is a JSON number representing the number of seconds from 1970-01-01T0:0:0Z as measured in UTC until the date/time.</summary>
    public const string UpdatedAt = "updated_at";

    /// <summary>The iat (issued at) claim identifies the time at which the JWT was issued, , specified as the number of seconds from 1970-01-01T0:0:0Z</summary>
    public const string IssuedAt = "iat";

    /// <summary>Authentication Methods References. JSON array of strings that are identifiers for authentication methods used in the authentication.</summary>
    public const string AuthenticationMethod = "amr";

    /// <summary>Session identifier. This represents a Session of an OP at an RP to a User Agent or device for a logged-in End-User. Its contents are unique to the OP and opaque to the RP.</summary>
    public const string SessionId = "sid";

    /// <summary>
    /// Authentication Context Class Reference. String specifying an Authentication Context Class Reference value that identifies the Authentication Context Class that the authentication performed satisfied. 
    /// The value "0" indicates the End-User authentication did not meet the requirements of ISO/IEC 29115 level 1. 
    /// Authentication using a long-lived browser cookie, for instance, is one example where the use of "level 0" is appropriate. 
    /// Authentications with level 0 SHOULD NOT be used to authorize access to any resource of any monetary value.
    ///  (This corresponds to the OpenID 2.0 PAPE nist_auth_level 0.) 
    /// An absolute URI or an RFC 6711 registered name SHOULD be used as the acr value; registered names MUST NOT be used with a different meaning than that which is registered. 
    /// Parties using this claim will need to agree upon the meanings of the values used, which may be context-specific. 
    /// The acr value is a case sensitive string.
    /// </summary>
    public const string AuthenticationContextClassReference = "acr";

    /// <summary>Time when the End-User authentication occurred. Its value is a JSON number representing the number of seconds from 1970-01-01T0:0:0Z as measured in UTC until the date/time. When a max_age request is made or when auth_time is requested as an Essential Claim, then this Claim is REQUIRED; otherwise, its inclusion is OPTIONAL.</summary>
    public const string AuthenticationTime = "auth_time";

    /// <summary>The party to which the ID Token was issued. If present, it MUST contain the OAuth 2.0 Client ID of this party. This Claim is only needed when the ID Token has a single audience value and that audience is different than the authorized party. It MAY be included even when the authorized party is the same as the sole audience. The azp value is a case sensitive string containing a StringOrURI value.</summary>
    public const string AuthorizedParty = "azp";

    /// <summary> Access Token hash value. Its value is the base64url encoding of the left-most half of the hash of the octets of the ASCII representation of the access_token value, where the hash algorithm used is the hash algorithm used in the alg Header Parameter of the ID Token's JOSE Header. For instance, if the alg is RS256, hash the access_token value with SHA-256, then take the left-most 128 bits and base64url encode them. The at_hash value is a case sensitive string.</summary>
    public const string AccessTokenHash = "at_hash";

    /// <summary>Code hash value. Its value is the base64url encoding of the left-most half of the hash of the octets of the ASCII representation of the code value, where the hash algorithm used is the hash algorithm used in the alg Header Parameter of the ID Token's JOSE Header. For instance, if the alg is HS512, hash the code value with SHA-512, then take the left-most 256 bits and base64url encode them. The c_hash value is a case sensitive string.</summary>
    public const string AuthorizationCodeHash = "c_hash";

    /// <summary>State hash value. Its value is the base64url encoding of the left-most half of the hash of the octets of the ASCII representation of the state value, where the hash algorithm used is the hash algorithm used in the alg Header Parameter of the ID Token's JOSE Header. For instance, if the alg is HS512, hash the code value with SHA-512, then take the left-most 256 bits and base64url encode them. The c_hash value is a case sensitive string.</summary>
    public const string StateHash = "s_hash";

    /// <summary>String value used to associate a Client session with an ID Token, and to mitigate replay attacks. The value is passed through unmodified from the Authentication Request to the ID Token. If present in the ID Token, Clients MUST verify that the nonce Claim Value is equal to the value of the nonce parameter sent in the Authentication Request. If present in the Authentication Request, Authorization Servers MUST include a nonce Claim in the ID Token with the Claim Value being the nonce value sent in the Authentication Request. Authorization Servers SHOULD perform no other processing on nonce values used. The nonce value is a case sensitive string.</summary>
    public const string Nonce = "nonce";

    /// <summary>JWT ID. A unique identifier for the token, which can be used to prevent reuse of the token. These tokens MUST only be used once, unless conditions for reuse were negotiated between the parties; any such negotiation is beyond the scope of this specification.</summary>
    public const string JwtId = "jti";

    /// <summary>Defines a set of event statements that each may add additional claims to fully describe a single logical event that has occurred.</summary>
    public const string Events = "events";

    /// <summary>OAuth 2.0 Client Identifier valid at the Authorization Server.</summary>
    public const string ClientId = "client_id";

    /// <summary>OpenID Connect requests MUST contain the "openid" scope value. If the openid scope value is not present, the behavior is entirely unspecified. Other scope values MAY be present. Scope values used that are not understood by an implementation SHOULD be ignored.</summary>
    public const string Scope = "scope";

    /// <summary>The "act" (actor) claim provides a means within a JWT to express that delegation has occurred and identify the acting party to whom authority has been delegated.The "act" claim value is a JSON object and members in the JSON object are claims that identify the actor. The claims that make up the "act" claim identify and possibly provide additional information about the actor.</summary>
    public const string Actor = "act";

    /// <summary>The "may_act" claim makes a statement that one party is authorized to become the actor and act on behalf of another party. The claim value is a JSON object and members in the JSON object are claims that identify the party that is asserted as being eligible to act for the party identified by the JWT containing the claim.</summary>
    public const string MayAct = "may_act";

    /// <summary>
    /// an identifier
    /// </summary>
    public const string Id = "id";

    /// <summary>
    /// The identity provider
    /// </summary>
    public const string IdentityProvider = "idp";

    /// <summary>
    /// The role
    /// </summary>
    public const string Role = "role";

    /// <summary>
    /// The reference token identifier
    /// </summary>
    public const string ReferenceTokenId = "reference_token_id";

    /// <summary>
    /// The confirmation
    /// </summary>
    public const string Confirmation = "cnf";

签名算法

  • HS256
    HS256 使用密钥生成固定的签名,RS256 使用成非对称进行签名。简单地说,HS256 必须与任何想要验证 JWT客户端API 共享秘密。与任何其他对称算法一样,相同的秘密用于签名和验证 JWTRS256 生成非对称签名,这意味着必须使用私钥来签签名 JWT,并且必须使用对应的公钥来验证签名。
  • RS256
    与对称算法不同,使用 RS256 可以保证服务端是 JWT 的签名者,因为服务端是唯一拥有私钥的一方。这样做将不再需要在许多应用程序之间共享私钥。
    使用非对称签名算法。这样做将不再需要在许多应用程序之间共享私钥。

案例

添加NuGet包:System.IdentityModel.Tokens.Jwt

1、HMACSHA256

JwtHelper(HMACSHA256)
/// <summary>
/// JwtToken生成、校验(HMACSHA256)
/// </summary>
public static class Jwt_HMACSHA256Helper
{
    private static string KEY = "f47b558d-7654-458c-99f2-123456ef0199";
    /// <summary>
    /// 生成token
    /// </summary>
    /// <returns></returns>
    public static string GetJwtToken()
    {
        //对称秘钥
        SecurityKey securityKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(KEY));

        var claims = new List<Claim>() {
            new Claim("ID","1"),
            new Claim("Name","fan")
        };
        JwtSecurityToken jwtToken = new JwtSecurityToken(
            issuer: "fan",
            audience: "fan",
            claims: claims,
            notBefore: DateTime.UtcNow,
            expires: DateTime.UtcNow.AddSeconds(10),
            signingCredentials: new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256)
            );

        //生成token方式1
        string token = new JwtSecurityTokenHandler().WriteToken(jwtToken);

        ////生成token方式2
        //var tokenDescriptor = new SecurityTokenDescriptor // 创建一个 Token 的原始对象
        //{
        //    Issuer = "fan",
        //    Audience = "fan",
        //    Subject = new ClaimsIdentity(new[]
        //           {
        //                new Claim(ClaimTypes.Name, "")
        //            }),
        //    Expires = DateTime.Now.AddMinutes(60),
        //    SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(Encoding.ASCII.GetBytes(key)), SecurityAlgorithms.HmacSha256)
        //};
        //SecurityToken securityToken = new JwtSecurityTokenHandler().CreateToken(tokenDescriptor);
        //var token2 = new JwtSecurityTokenHandler().WriteToken(securityToken);

        return token;
    }
    /// <summary>
    /// 校验token
    /// </summary>
    /// <param name="token"></param>
    /// <param name="principal"></param>
    /// <returns></returns>
    public static bool VerifyJwtToken(string token, out ClaimsPrincipal principal)
    {
        principal = null;
        //对称秘钥
        SecurityKey securityKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(KEY));
        //校验token
        var validateParameter = new TokenValidationParameters()
        {
            ValidateLifetime = true,
            ValidateAudience = true,
            ValidateIssuer = true,
            ValidateIssuerSigningKey = true,
            ValidIssuer = "fan",
            ValidAudience = "fan",
            IssuerSigningKey = securityKey,
            ClockSkew = TimeSpan.Zero//校验过期时间必须加此属性
        };
        //不校验,直接解析token
        //jwtToken = new JwtSecurityTokenHandler().ReadJwtToken(token1);
        bool success = false;
        try
        {
            //校验并解析token,validatedToken是解密后的对象
            principal = new JwtSecurityTokenHandler().ValidateToken(token, validateParameter, out SecurityToken validatedToken);
            //获取payload中的数据 
            //var jwtPayload = ((JwtSecurityToken)validatedToken).Payload.SerializeToJson(); 
            success = true;

        }
        catch (SecurityTokenExpiredException ex)
        {
            //表示过期
            success = false;
        }
        catch (SecurityTokenException ex)
        {
            //表示token错误
            success = false;
        }
        catch (Exception ex)
        {
            success = false;
        }
        return success;
    }
}
static void Main()
{
    string token = Jwt_HMACSHA256Helper.GetJwtToken();
    bool success = Jwt_HMACSHA256Helper.VerifyJwtToken(token, out ClaimsPrincipal principal);
}

2、RSA

RSA公私钥生成地址:https://uutool.cn/rsa-generate/

JwtHelper(RSA)
    /// <summary>
    /// JwtToken生成、校验(RSA)
    /// </summary>
    public static class Jwt_RSAHelper
    {
        //RSA私钥
        private static string PRIVATE_KEY = @"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
S2xOANqreXnJutzv4tVJGjp1I7YmDeU=";
        //RSA公钥
        private static string PUBLIC_KEY = @"MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAuXGzXP/GHpe6U0+xWQqy
Bs1qBBzP3OW1bVBU6sQqKU1Ef5IjK8Qoej4d7mjYQk5keq9OOu2d4WnVp5SiqqJQ
wCOY74dBFa5JhAGvlW1gk3hewtwtGFtq0LfLtlTzs1QFeqX+IWZoKksLfK6yZn6w
1Ol1tv2UYeHuTLwM0zcaEqyHwUl1+B2gc86zu2evv9TxQWZgIEemrHJu7QQL59Z4
BRE15v7kHUc/mLq9uYFT+a2Ftq7mcQWgfIphTGs4SZzKV0vRLwWsERSwyfrs4YyD
L0NvqswWq3NNJF0ascc3/TUor+rjHi98L+Shi+Ga1ItMCKXbjnVcAXSwX47c8gL5
qPZkl0r9Csbp3vK0Ukc91ZvkTYZ7IDCbqHU7db7QsdtVyz92vJu45cJbGuwDGqwq
P0ExYKbf5zAVXv25Gd3aBLRt/s7sQOOWWNn1XbIdtpOdiD124ZiY1tA7J+BqHV4E
Wlu0azu6lS7q1GSfMPiK/i6ltB1H7xVaW9Mw9PxHr/ZtO/mZ1B4XDeoMSCWv1wgS
zk+U03AB/qF8Z4OeIZhhPZ4fqCfhQKEfT7sZInCcFzhFr3gMlWN5+THcFBlcLi+f
ntnsMEYYXBw8UKB3OZV0u8ZJ0xp6/yj+45lRgBU6gVCW81elhgdE65LBUlsEy+UI
0Eeb2Hq73mdGpgzQ/Z1w0WcCAwEAAQ==";

        public static string GetJwtToken()
        {
            var claims = new List<Claim>
            {
                new Claim(JwtRegisteredClaimNames.Name, "fan")
            };
            var rsa = RSA.Create();
            rsa.ImportPkcs8PrivateKey(Convert.FromBase64String(PRIVATE_KEY), out _);
            SecurityKey securityKey = new RsaSecurityKey(rsa);
            var token = new JwtSecurityToken(
                issuer: "fan",
                audience: "fan",
                claims: claims,
                notBefore: DateTime.Now,
                expires: DateTime.Now.AddSeconds(10),
                signingCredentials: new SigningCredentials(securityKey, SecurityAlgorithms.RsaSha256)
            );

            var jwtToken = new JwtSecurityTokenHandler().WriteToken(token);

            return jwtToken;
        }
        public static bool VerifyJwtToken(string token, out ClaimsPrincipal principal)
        {
            principal = null;
            //校验token
            var validateParameter = new TokenValidationParameters()
            {
                ValidateLifetime = true,
                ValidateAudience = true,
                ValidateIssuer = true,
                ValidateIssuerSigningKey = true,
                ValidIssuer = "fan",
                ValidAudience = "fan",
                IssuerSigningKey = new RsaSecurityKey(CreateRsaProviderFromPublicKey(PUBLIC_KEY)),

                ClockSkew = TimeSpan.Zero//校验过期时间必须加此属性
            };
            bool success = false;
            try
            {
                //校验并解析token,validatedToken是解密后的对象
                principal = new JwtSecurityTokenHandler().ValidateToken(token, validateParameter, out SecurityToken validatedToken);
                //获取payload中的数据 
                //var jwtPayload = ((JwtSecurityToken)validatedToken).Payload.SerializeToJson(); 
                success = true;

            }
            catch (SecurityTokenExpiredException ex)
            {
                //表示过期
                success = false;
            }
            catch (SecurityTokenException ex)
            {
                //表示token错误
                success = false;
            }
            catch (Exception ex)
            {
                success = false;
            }
            return success;
        }


        #region 私有方法
        /// <summary>
        /// 通过公钥创建RSA
        /// </summary>
        /// <param name="publicKeyString"></param>
        /// <returns></returns>
        private static RSA CreateRsaProviderFromPublicKey(string publicKeyString)
        {
            // encoded OID sequence for  PKCS #1 rsaEncryption szOID_RSA_RSA = "1.2.840.113549.1.1.1"
            byte[] seqOid = { 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00 };
            byte[] seq = new byte[15];
            var x509Key = Convert.FromBase64String(publicKeyString);
            // ---------  Set up stream to read the asn.1 encoded SubjectPublicKeyInfo blob  ------
            using (MemoryStream mem = new MemoryStream(x509Key))
            {
                using (BinaryReader binr = new BinaryReader(mem))  //wrap Memory Stream with BinaryReader for easy reading
                {
                    byte bt = 0;
                    ushort twobytes = 0;

                    twobytes = binr.ReadUInt16();
                    if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81)
                        binr.ReadByte();    //advance 1 byte
                    else if (twobytes == 0x8230)
                        binr.ReadInt16();   //advance 2 bytes
                    else
                        return null;

                    seq = binr.ReadBytes(15);       //read the Sequence OID
                    if (!CompareBytearrays(seq, seqOid))    //make sure Sequence for OID is correct
                        return null;

                    twobytes = binr.ReadUInt16();
                    if (twobytes == 0x8103) //data read as little endian order (actual data order for Bit String is 03 81)
                        binr.ReadByte();    //advance 1 byte
                    else if (twobytes == 0x8203)
                        binr.ReadInt16();   //advance 2 bytes
                    else
                        return null;

                    bt = binr.ReadByte();
                    if (bt != 0x00)     //expect null byte next
                        return null;

                    twobytes = binr.ReadUInt16();
                    if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81)
                        binr.ReadByte();    //advance 1 byte
                    else if (twobytes == 0x8230)
                        binr.ReadInt16();   //advance 2 bytes
                    else
                        return null;

                    twobytes = binr.ReadUInt16();
                    byte lowbyte = 0x00;
                    byte highbyte = 0x00;

                    if (twobytes == 0x8102) //data read as little endian order (actual data order for Integer is 02 81)
                        lowbyte = binr.ReadByte();  // read next bytes which is bytes in modulus
                    else if (twobytes == 0x8202)
                    {
                        highbyte = binr.ReadByte(); //advance 2 bytes
                        lowbyte = binr.ReadByte();
                    }
                    else
                        return null;
                    byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };   //reverse byte order since asn.1 key uses big endian order
                    int modsize = BitConverter.ToInt32(modint, 0);

                    int firstbyte = binr.PeekChar();
                    if (firstbyte == 0x00)
                    {   //if first byte (highest order) of modulus is zero, don't include it
                        binr.ReadByte();    //skip this null byte
                        modsize -= 1;   //reduce modulus buffer size by 1
                    }

                    byte[] modulus = binr.ReadBytes(modsize);   //read the modulus bytes

                    if (binr.ReadByte() != 0x02)            //expect an Integer for the exponent data
                        return null;
                    int expbytes = (int)binr.ReadByte();        // should only need one byte for actual exponent data (for all useful values)
                    byte[] exponent = binr.ReadBytes(expbytes);

                    // ------- create RSACryptoServiceProvider instance and initialize with public key -----
                    var rsa = RSA.Create();
                    RSAParameters rsaKeyInfo = new RSAParameters
                    {
                        Modulus = modulus,
                        Exponent = exponent
                    };
                    rsa.ImportParameters(rsaKeyInfo);

                    return rsa;
                }

            }
        }
        private static bool CompareBytearrays(byte[] a, byte[] b)
        {
            if (a.Length != b.Length)
                return false;
            int i = 0;
            foreach (byte c in a)
            {
                if (c != b[i])
                    return false;
                i++;
            }
            return true;
        }
        #endregion
    }
string token = Jwt_RSAHelper.GetJwtToken();
bool success = Jwt_RSAHelper.VerifyJwtToken(token, out ClaimsPrincipal principal);

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2022-03-09
  • 2021-07-23
  • 2021-05-20
  • 2022-01-07
  • 2021-11-03
  • 2022-12-23
猜你喜欢
  • 2021-09-06
  • 2021-06-24
  • 2022-12-23
  • 2022-02-02
  • 2022-02-07
  • 2022-01-07
  • 2021-11-30
相关资源
相似解决方案