การพิสูจน์ตัวตน JWT สำหรับ ASP.NET Web API


264

ฉันพยายามสนับสนุนโทเค็นผู้ถือ JWT (JSON Web Token) ในแอปพลิเคชันเว็บ API ของฉันและฉันหลงทาง

ฉันเห็นการสนับสนุน. NET Core และสำหรับแอปพลิเคชัน OWIN
ฉันกำลังโฮสต์แอปพลิเคชันของฉันใน IIS

ฉันจะบรรลุโมดูลการรับรองความถูกต้องนี้ในแอปพลิเคชันของฉันได้อย่างไร มีวิธีใดบ้างที่ฉันสามารถใช้การ<authentication>กำหนดค่าที่คล้ายกับวิธีที่ฉันใช้การตรวจสอบสิทธิ์แบบฟอร์ม / Windows

คำตอบ:


611

ฉันตอบคำถามนี้: วิธีรักษาความปลอดภัย ASP.NET Web API 4 ปีที่แล้วโดยใช้ HMAC

ตอนนี้สิ่งต่างๆมากมายเปลี่ยนไปในเรื่องความปลอดภัยโดยเฉพาะ JWT กำลังได้รับความนิยม ที่นี่ฉันจะพยายามอธิบายวิธีการใช้ JWT ในวิธีที่ง่ายที่สุดและพื้นฐานที่ฉันสามารถทำได้ดังนั้นเราจะไม่หลงทางจาก OWIN, Oauth2, ASP.NET Identity ... :)

หากคุณไม่รู้จักโทเค็น JWT คุณจะต้องดูที่:

https://tools.ietf.org/html/rfc7519

โดยทั่วไปโทเค็น JWT ดูเหมือนว่า:

<base64-encoded header>.<base64-encoded claims>.<base64-encoded signature>

ตัวอย่าง:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1bmlxdWVfbmFtZSI6ImN1b25nIiwibmJmIjoxNDc3NTY1NzI0LCJleHAiOjE0Nzc1NjY5MjQsImlhdCI6MTQ3NzU2NTcyNH0.6MzD1VwA5AcOcajkFyKhLYybr3h13iZjDyHm9zysDFQ

โทเค็น JWT มีสามส่วน:

  1. ส่วนหัว: รูปแบบ JSON ซึ่งเข้ารหัสใน Base64
  2. การอ้างสิทธิ์: รูปแบบ JSON ซึ่งเข้ารหัสใน Base64
  3. ลายเซ็น: สร้างและเซ็นชื่อตามส่วนหัวและการอ้างสิทธิ์ซึ่งเข้ารหัสใน Base64

หากคุณใช้เว็บไซต์jwt.ioด้วยโทเค็นด้านบนคุณสามารถถอดรหัสโทเค็นและดูได้ดังนี้:

ป้อนคำอธิบายรูปภาพที่นี่

ในทางเทคนิค JWT ใช้ลายเซ็นซึ่งลงนามจากส่วนหัวและการเรียกร้องด้วยอัลกอริทึมความปลอดภัยที่ระบุไว้ในส่วนหัว (ตัวอย่าง: HMACSHA256) ดังนั้น JWT จะต้องถูกถ่ายโอนผ่าน HTTPs หากคุณเก็บข้อมูลที่ละเอียดอ่อนใด ๆ ไว้ในการอ้างสิทธิ์

ตอนนี้เพื่อที่จะใช้การพิสูจน์ตัวตน JWT คุณไม่จำเป็นต้องใช้มิดเดิลแวร์ OWIN จริงๆถ้าคุณมีระบบ Web Api ดั้งเดิม แนวคิดง่าย ๆ คือวิธีการมอบโทเค็น JWT และวิธีการตรวจสอบโทเค็นเมื่อมีคำขอมา แค่นั้นแหละ.

กลับไปที่การสาธิตเพื่อให้โทเค็น JWT มีน้ำหนักเบาฉันเก็บusernameและใช้expiration timeJWT เท่านั้น แต่ด้วยวิธีนี้คุณต้องสร้างข้อมูลประจำตัวในท้องถิ่นใหม่ (เงินต้น) เพื่อเพิ่มข้อมูลเพิ่มเติมเช่น: role .. หากคุณต้องการให้สิทธิ์ในบทบาท แต่ถ้าคุณต้องการเพิ่มข้อมูลเข้าไปใน JWT มันขึ้นอยู่กับคุณ: มันยืดหยุ่นมาก

แทนที่จะใช้มิดเดิลแวร์ OWIN คุณสามารถระบุจุดสิ้นสุดโทเค็น JWT โดยใช้การดำเนินการจากคอนโทรลเลอร์:

public class TokenController : ApiController
{
    // This is naive endpoint for demo, it should use Basic authentication
    // to provide token or POST request
    [AllowAnonymous]
    public string Get(string username, string password)
    {
        if (CheckUser(username, password))
        {
            return JwtManager.GenerateToken(username);
        }

        throw new HttpResponseException(HttpStatusCode.Unauthorized);
    }

    public bool CheckUser(string username, string password)
    {
        // should check in the database
        return true;
    }
}

นี่คือการกระทำที่ไร้เดียงสา; ในการผลิตคุณควรใช้คำขอ POST หรือจุดสิ้นสุดการรับรองความถูกต้องเบื้องต้นเพื่อให้โทเค็น JWT

จะสร้างโทเค็นได้usernameอย่างไร?

คุณสามารถใช้แพคเกจ NuGet ที่เรียกSystem.IdentityModel.Tokens.Jwtจาก Microsoft เพื่อสร้างโทเค็นหรือแม้แต่แพ็คเกจอื่นหากคุณต้องการ ในการสาธิตฉันใช้HMACSHA256กับSymmetricKey:

/// <summary>
/// Use the below code to generate symmetric Secret Key
///     var hmac = new HMACSHA256();
///     var key = Convert.ToBase64String(hmac.Key);
/// </summary>
private const string Secret = "db3OIsj+BXE9NZDy0t8W3TcNekrF+2d/1sFnWG4HnV8TZY30iTOdtVWJG8abWvB1GlOgJuQZdcF2Luqm/hccMw==";

public static string GenerateToken(string username, int expireMinutes = 20)
{
    var symmetricKey = Convert.FromBase64String(Secret);
    var tokenHandler = new JwtSecurityTokenHandler();

    var now = DateTime.UtcNow;
    var tokenDescriptor = new SecurityTokenDescriptor
    {
        Subject = new ClaimsIdentity(new[]
        {
            new Claim(ClaimTypes.Name, username)
        }),

        Expires = now.AddMinutes(Convert.ToInt32(expireMinutes)),

        SigningCredentials = new SigningCredentials(
            new SymmetricSecurityKey(symmetricKey), 
            SecurityAlgorithms.HmacSha256Signature)
    };

    var stoken = tokenHandler.CreateToken(tokenDescriptor);
    var token = tokenHandler.WriteToken(stoken);

    return token;
}

ปลายทางเพื่อจัดเตรียมโทเค็น JWT เสร็จสิ้นแล้ว ตอนนี้วิธีการตรวจสอบ JWT เมื่อคำขอมา? ในการสาธิตฉันได้สร้าง JwtAuthenticationAttributeสิ่งที่สืบทอดมาIAuthenticationFilter(รายละเอียดเพิ่มเติมเกี่ยวกับตัวกรองการรับรองความถูกต้องที่นี่ )

ด้วยแอตทริบิวต์นี้คุณสามารถรับรองความถูกต้องของการกระทำใด ๆ : คุณเพียงแค่ต้องใส่คุณลักษณะนี้ในการกระทำนั้น

public class ValueController : ApiController
{
    [JwtAuthentication]
    public string Get()
    {
        return "value";
    }
}

คุณยังสามารถใช้มิดเดิลแวร์ OWIN หรือ DelegateHander หากคุณต้องการตรวจสอบคำขอขาเข้าทั้งหมดสำหรับ WebAPI ของคุณ (ไม่เฉพาะเจาะจงกับตัวควบคุมหรือการกระทำ)

ด้านล่างเป็นวิธีการหลักจากตัวกรองการรับรองความถูกต้อง:

private static bool ValidateToken(string token, out string username)
{
    username = null;

    var simplePrinciple = JwtManager.GetPrincipal(token);
    var identity = simplePrinciple.Identity as ClaimsIdentity;

    if (identity == null)
        return false;

    if (!identity.IsAuthenticated)
        return false;

    var usernameClaim = identity.FindFirst(ClaimTypes.Name);
    username = usernameClaim?.Value;

    if (string.IsNullOrEmpty(username))
       return false;

    // More validate to check whether username exists in system

    return true;
}

protected Task<IPrincipal> AuthenticateJwtToken(string token)
{
    string username;

    if (ValidateToken(token, out username))
    {
        // based on username to get more information from database 
        // in order to build local identity
        var claims = new List<Claim>
        {
            new Claim(ClaimTypes.Name, username)
            // Add more claims if needed: Roles, ...
        };

        var identity = new ClaimsIdentity(claims, "Jwt");
        IPrincipal user = new ClaimsPrincipal(identity);

        return Task.FromResult(user);
    }

    return Task.FromResult<IPrincipal>(null);
}

ขั้นตอนการทำงานคือการใช้ห้องสมุด JWT (NuGet แพคเกจข้างต้น) เพื่อตรวจสอบ JWT ClaimsPrincipalโทเค็นแล้วส่งกลับมา คุณสามารถทำการตรวจสอบเพิ่มเติมเช่นตรวจสอบว่ามีผู้ใช้อยู่ในระบบของคุณและเพิ่มการตรวจสอบความถูกต้องแบบกำหนดเองอื่น ๆ หากคุณต้องการ รหัสเพื่อตรวจสอบโทเค็น JWT และรับเงินต้นคืน:

public static ClaimsPrincipal GetPrincipal(string token)
{
    try
    {
        var tokenHandler = new JwtSecurityTokenHandler();
        var jwtToken = tokenHandler.ReadToken(token) as JwtSecurityToken;

        if (jwtToken == null)
            return null;

        var symmetricKey = Convert.FromBase64String(Secret);

        var validationParameters = new TokenValidationParameters()
        {
            RequireExpirationTime = true,
            ValidateIssuer = false,
            ValidateAudience = false,
            IssuerSigningKey = new SymmetricSecurityKey(symmetricKey)
        };

        SecurityToken securityToken;
        var principal = tokenHandler.ValidateToken(token, validationParameters, out securityToken);

        return principal;
    }
    catch (Exception)
    {
        //should write log
        return null;
    }
}

หากโทเค็น JWT ได้รับการตรวจสอบความถูกต้องแล้วและคืนเงินต้นคุณควรสร้างข้อมูลประจำตัวในท้องถิ่นใหม่และใส่ข้อมูลเพิ่มเติมเพื่อตรวจสอบการอนุญาตบทบาท

อย่าลืมเพิ่มconfig.Filters.Add(new AuthorizeAttribute());(การอนุญาตเริ่มต้น) ที่ขอบเขตทั่วโลกเพื่อป้องกันการร้องขอที่ไม่ระบุชื่อใด ๆ ไปยังแหล่งข้อมูลของคุณ

คุณสามารถใช้บุรุษไปรษณีย์เพื่อทดสอบตัวอย่าง:

คำขอโทเค็น (ไร้เดียงสาที่ฉันกล่าวถึงข้างต้นเพียงเพื่อการสาธิต)

GET http://localhost:{port}/api/token?username=cuong&password=1

ใส่โทเค็น JWT ในส่วนหัวสำหรับคำขอที่ได้รับอนุญาตตัวอย่าง:

GET http://localhost:{port}/api/value

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1bmlxdWVfbmFtZSI6ImN1b25nIiwibmJmIjoxNDc3NTY1MjU4LCJleHAiOjE0Nzc1NjY0NTgsImlhdCI6MTQ3NzU2NTI1OH0.dSwwufd4-gztkLpttZsZ1255oEzpWCJkayR_4yvNL1s

ตัวอย่างจะถูกวางไว้ที่นี่: https://github.com/cuongle/WebApi.Jwt


5
อธิบายได้ดีโดย @Cuong Le แต่ฉันต้องการเพิ่มมากขึ้น: หากคุณใช้ OWIN ให้ตรวจสอบ UseJwtBearerAuthentication ที่มีอยู่ใน Microsoft.Owin.Security.Jwt คุณสามารถใช้ Owin มิดเดิลแวร์นี้บน WebAPI เพื่อตรวจสอบคำขอทั้งหมดที่เข้ามาโดยอัตโนมัติ ใช้คลาสเริ่มต้น owin เพื่อลงทะเบียนมิดเดิลแวร์
Jek

5
@AmirPopovich คุณไม่จำเป็นต้องตั้งโทเค็นในการตอบสนองโทเค็นจะต้องถูกเก็บไว้ที่อื่นในฝั่งไคลเอ็นต์สำหรับเว็บคุณสามารถใส่ที่จัดเก็บในตัวเครื่องเมื่อใดก็ตามที่คุณส่งคำขอ HTTP ใส่โทเค็นที่ส่วนหัว
cuongle

7
ว้าวนี่เป็นคำอธิบายที่ง่ายที่สุดที่ฉันเคยเห็นมานาน +100 ถ้าทำได้
gyozo kudor

4
@Homam: ขออภัยคำตอบนี้ล่าช้าวิธีที่ดีที่สุดในการสร้างคือ: varhmac = new HMACSHA256();var key = Convert.ToBase64String(hmac.Key);
cuongle

4
ทุกคนที่ใช้รหัสสาธิตจาก repo ของ CuongLe จะสังเกตเห็นว่ามีข้อผิดพลาดที่ไม่ได้รับการจัดการส่วนหัวของคำร้องขอซึ่งหมายถึงการสอบถามใด ๆ โดยที่ไม่มีใครสามารถผ่านไปได้ มีคำขอดึงจาก @magicleon เพื่อแก้ไขปัญหานี้ได้ที่นี่: github.com/cuongle/WebApi.Jwt/pull/4
Chucky

11

ฉันพยายามทำให้สำเร็จด้วยความพยายามเพียงเล็กน้อย (เช่นเดียวกับ ASP.NET Core)

เพื่อที่ฉันจะใช้Startup.csไฟล์และMicrosoft.Owin.Security.Jwtห้องสมุดOWIN

เพื่อให้แอปเข้าชมStartup.csเราจำเป็นต้องแก้ไขWeb.config:

<configuration>
  <appSettings>
    <add key="owin:AutomaticAppStartup" value="true" />
    ...

นี่คือวิธีที่Startup.csควรดู:

using MyApp.Helpers;
using Microsoft.IdentityModel.Tokens;
using Microsoft.Owin;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Jwt;
using Owin;

[assembly: OwinStartup(typeof(MyApp.App_Start.Startup))]

namespace MyApp.App_Start
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.UseJwtBearerAuthentication(
                new JwtBearerAuthenticationOptions
                {
                    AuthenticationMode = AuthenticationMode.Active,
                    TokenValidationParameters = new TokenValidationParameters()
                    {
                        ValidAudience = ConfigHelper.GetAudience(),
                        ValidIssuer = ConfigHelper.GetIssuer(),
                        IssuerSigningKey = ConfigHelper.GetSymmetricSecurityKey(),
                        ValidateLifetime = true,
                        ValidateIssuerSigningKey = true
                    }
                });
        }
    }
}

พวกคุณหลายคนใช้ ASP.NET Core ทุกวันนี้ดังนั้นคุณจะเห็นได้ว่ามันไม่ได้แตกต่างจากที่เรามีอยู่มากนัก

มันทำให้ฉันงุนงงจริงๆก่อนฉันพยายามใช้ผู้ให้บริการที่กำหนดเองเป็นต้น แต่ฉันไม่ได้คาดหวังว่ามันจะง่าย OWINแค่หิน!

สิ่งเดียวที่จะพูดถึง - หลังจากที่ฉันเปิดใช้งาน OWIN Startup NSWaglibrary หยุดทำงานสำหรับฉัน (เช่นบางคนอาจต้องการสร้างพรอกซี HTTP HTTP ของพร็อกซีอัตโนมัติสำหรับแอปเชิงมุม)

วิธีการแก้ก็ง่ายมาก - ฉันแทนที่NSWagด้วยSwashbuckleและไม่มีปัญหาเพิ่มเติม


ตกลงตอนนี้แชร์ConfigHelperรหัส:

public class ConfigHelper
{
    public static string GetIssuer()
    {
        string result = System.Configuration.ConfigurationManager.AppSettings["Issuer"];
        return result;
    }

    public static string GetAudience()
    {
        string result = System.Configuration.ConfigurationManager.AppSettings["Audience"];
        return result;
    }

    public static SigningCredentials GetSigningCredentials()
    {
        var result = new SigningCredentials(GetSymmetricSecurityKey(), SecurityAlgorithms.HmacSha256);
        return result;
    }

    public static string GetSecurityKey()
    {
        string result = System.Configuration.ConfigurationManager.AppSettings["SecurityKey"];
        return result;
    }

    public static byte[] GetSymmetricSecurityKeyAsBytes()
    {
        var issuerSigningKey = GetSecurityKey();
        byte[] data = Encoding.UTF8.GetBytes(issuerSigningKey);
        return data;
    }

    public static SymmetricSecurityKey GetSymmetricSecurityKey()
    {
        byte[] data = GetSymmetricSecurityKeyAsBytes();
        var result = new SymmetricSecurityKey(data);
        return result;
    }

    public static string GetCorsOrigins()
    {
        string result = System.Configuration.ConfigurationManager.AppSettings["CorsOrigins"];
        return result;
    }
}

สิ่งสำคัญอีกประการหนึ่ง - ฉันส่ง JWT Token ผ่านส่วนหัวการอนุญาตดังนั้นรหัส typescript จะมองหาฉันดังนี้:

(รหัสด้านล่างถูกสร้างโดยNSWag )

@Injectable()
export class TeamsServiceProxy {
    private http: HttpClient;
    private baseUrl: string;
    protected jsonParseReviver: ((key: string, value: any) => any) | undefined = undefined;

    constructor(@Inject(HttpClient) http: HttpClient, @Optional() @Inject(API_BASE_URL) baseUrl?: string) {
        this.http = http;
        this.baseUrl = baseUrl ? baseUrl : "https://localhost:44384";
    }

    add(input: TeamDto | null): Observable<boolean> {
        let url_ = this.baseUrl + "/api/Teams/Add";
        url_ = url_.replace(/[?&]$/, "");

        const content_ = JSON.stringify(input);

        let options_ : any = {
            body: content_,
            observe: "response",
            responseType: "blob",
            headers: new HttpHeaders({
                "Content-Type": "application/json", 
                "Accept": "application/json",
                "Authorization": "Bearer " + localStorage.getItem('token')
            })
        };

ดูส่วนหัว - "Authorization": "Bearer " + localStorage.getItem('token')


I replaced NSWag with Swashbuckle and didn't have any further issues.Swashbuckle มีความสามารถในการสร้างไฟล์ typescript หรือว่าเป็นสิ่งที่คุณเพิ่มเข้าไปเอง?
บดขยี้

@crush swashbucle เป็น backend library ที่ให้ json เช่นเดียวกับ nuget nswag library ที่ดีกว่าเท่านั้น เพื่อผลิตไฟล์ typescript คุณยังควรใช้แพ็คเกจ nswag ตั้งแต่ npm
Alex Herman

ใช่ฉันมี swashbuckle ในโปรเจ็กต์ของฉันมาระยะหนึ่งแล้วมันฟังดูเหมือนว่าคุณแนะนำว่ามันสามารถสร้างแบบจำลอง TypeScript แทน nswag ฉันไม่ใช่แฟนของ nswag ... มันหนัก ฉันได้สร้าง C # ของตัวเอง -> การแปลงแบบอักษรที่เชื่อมต่อกับ Swashbuckle - สร้างไฟล์เป็นกระบวนการหลังการสร้างและเผยแพร่ไปยังฟีด npm สำหรับโครงการของเรา ฉันแค่อยากจะทำให้แน่ใจว่าฉันไม่ได้มองข้ามโครงการ Swashbuckle ที่ทำสิ่งเดียวกันอยู่แล้ว
บดขยี้

8

นี่คือการใช้งานการพิสูจน์ตัวจริงแบบอ้างสิทธิ์น้อยที่สุดและปลอดภัยโดยใช้โทเค็น JWT ใน ASP.NET Core Web API

ก่อนอื่นคุณต้องแสดงจุดปลายที่ส่งคืนโทเค็น JWT ด้วยการอ้างสิทธิ์ที่กำหนดให้กับผู้ใช้:

 /// <summary>
        /// Login provides API to verify user and returns authentication token.
        /// API Path:  api/account/login
        /// </summary>
        /// <param name="paramUser">Username and Password</param>
        /// <returns>{Token: [Token] }</returns>
        [HttpPost("login")]
        [AllowAnonymous]
        public async Task<IActionResult> Login([FromBody] UserRequestVM paramUser, CancellationToken ct)
        {

            var result = await UserApplication.PasswordSignInAsync(paramUser.Email, paramUser.Password, false, lockoutOnFailure: false);

            if (result.Succeeded)
            {
                UserRequestVM request = new UserRequestVM();
                request.Email = paramUser.Email;


                ApplicationUser UserDetails = await this.GetUserByEmail(request);
                List<ApplicationClaim> UserClaims = await this.ClaimApplication.GetListByUser(UserDetails);

                var Claims = new ClaimsIdentity(new Claim[]
                                {
                                    new Claim(JwtRegisteredClaimNames.Sub, paramUser.Email.ToString()),
                                    new Claim(UserId, UserDetails.UserId.ToString())
                                });


                //Adding UserClaims to JWT claims
                foreach (var item in UserClaims)
                {
                    Claims.AddClaim(new Claim(item.ClaimCode, string.Empty));
                }

                var tokenHandler = new JwtSecurityTokenHandler();
                  // this information will be retrived from you Configuration
                //I have injected Configuration provider service into my controller
                var encryptionkey = Configuration["Jwt:Encryptionkey"];
                var key = Encoding.ASCII.GetBytes(encryptionkey);
                var tokenDescriptor = new SecurityTokenDescriptor
                {
                    Issuer = Configuration["Jwt:Issuer"],
                    Subject = Claims,

                // this information will be retrived from you Configuration
                //I have injected Configuration provider service into my controller
                    Expires = DateTime.UtcNow.AddMinutes(Convert.ToDouble(Configuration["Jwt:ExpiryTimeInMinutes"])),

                    //algorithm to sign the token
                    SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)

                };

                var token = tokenHandler.CreateToken(tokenDescriptor);
                var tokenString = tokenHandler.WriteToken(token);

                return Ok(new
                {
                    token = tokenString
                });
            }

            return BadRequest("Wrong Username or password");
        }

ตอนนี้คุณต้องเพิ่มการรับรองความถูกต้องให้กับบริการของคุณConfigureServicesในภายในstartup.csของคุณเพื่อเพิ่มการรับรองความถูกต้อง JWT เป็นบริการการรับรองความถูกต้องเริ่มต้นของคุณเช่นนี้:

services.AddAuthentication(x =>
            {
                x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            })
             .AddJwtBearer(cfg =>
             {
                 cfg.RequireHttpsMetadata = false;
                 cfg.SaveToken = true;
                 cfg.TokenValidationParameters = new TokenValidationParameters()
                 {
                     //ValidateIssuerSigningKey = true,
                     IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration["JWT:Encryptionkey"])),
                     ValidateAudience = false,
                     ValidateLifetime = true,
                     ValidIssuer = configuration["Jwt:Issuer"],
                     //ValidAudience = Configuration["Jwt:Audience"],
                     //IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JWT:Key"])),
                 };
             });

ตอนนี้คุณสามารถเพิ่มนโยบายลงในบริการการอนุญาตของคุณเช่นนี้:

services.AddAuthorization(options =>
            {
                options.AddPolicy("YourPolicyNameHere",
                                policy => policy.RequireClaim("YourClaimNameHere"));
            });

ทางเลือกนอกจากนี้คุณยังสามารถ (ไม่จำเป็น) เติมการอ้างสิทธิ์ทั้งหมดของคุณจากฐานข้อมูลของคุณเนื่องจากจะทำงานเพียงครั้งเดียวเมื่อเริ่มต้นแอปพลิเคชันของคุณและเพิ่มลงในนโยบายเช่นนี้:

  services.AddAuthorization(async options =>
            {
                var ClaimList = await claimApplication.GetList(applicationClaim);
                foreach (var item in ClaimList)
                {                        
                    options.AddPolicy(item.ClaimCode, policy => policy.RequireClaim(item.ClaimCode));                       
                }
            });

ตอนนี้คุณสามารถวางตัวกรองนโยบายในวิธีใด ๆ ที่คุณต้องการให้อนุญาตเช่นนี้:

 [HttpPost("update")]
        [Authorize(Policy = "ACC_UP")]
        public async Task<IActionResult> Update([FromBody] UserRequestVM requestVm, CancellationToken ct)
        {
//your logic goes here
}

หวังว่านี่จะช่วยได้


3

ฉันคิดว่าคุณควรใช้เซิร์ฟเวอร์ปาร์ตี้สามมิติเพื่อสนับสนุนโทเค็น JWT และไม่มีการสนับสนุน JWT ในกล่อง WEB API 2

อย่างไรก็ตามมีโครงการ OWIN สำหรับสนับสนุนโทเค็นที่เซ็นชื่อบางรูปแบบ (ไม่ใช่ JWT) มันทำหน้าที่เป็นโปรโตคอล OAuth ที่ลดลงเพื่อมอบรูปแบบการตรวจสอบสิทธิ์ที่เรียบง่ายสำหรับเว็บไซต์

คุณสามารถอ่านเพิ่มเติมเกี่ยวกับเรื่องนี้เช่นที่นี่

ค่อนข้างยาว แต่ส่วนใหญ่เป็นรายละเอียดกับคอนโทรลเลอร์และ ASP.NET Identity ที่คุณอาจไม่ต้องการเลย ที่สำคัญที่สุดคือ

ขั้นตอนที่ 9: เพิ่มการรองรับ OAuth Bearer Tokens Generation

ขั้นตอนที่ 12: ทดสอบ Back-end API

คุณสามารถอ่านวิธีการตั้งค่าจุดปลาย (เช่น "/ token") ที่คุณสามารถเข้าถึงได้จากส่วนหน้า (และรายละเอียดเกี่ยวกับรูปแบบของคำขอ)

ขั้นตอนอื่น ๆ ให้รายละเอียดเกี่ยวกับวิธีเชื่อมต่อจุดปลายทางนั้นกับฐานข้อมูล ฯลฯ และคุณสามารถเลือกชิ้นส่วนที่คุณต้องการ


2

ในกรณีของฉัน JWT ถูกสร้างขึ้นโดย API แยกต่างหากดังนั้น ASP.NET จำเป็นต้องถอดรหัสและตรวจสอบความถูกต้องเท่านั้น ตรงกันข้ามกับคำตอบที่ยอมรับเรากำลังใช้ RSA ซึ่งเป็นอัลกอริทึมที่ไม่สมมาตรดังนั้นSymmetricSecurityKeyคลาสที่กล่าวถึงข้างต้นจะไม่ทำงาน

นี่คือผลลัพธ์

using Microsoft.IdentityModel.Protocols;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Microsoft.IdentityModel.Tokens;
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Threading;
using System.Threading.Tasks;

    public static async Task<JwtSecurityToken> VerifyAndDecodeJwt(string accessToken)
    {
        try
        {
            var configurationManager = new ConfigurationManager<OpenIdConnectConfiguration>($"{securityApiOrigin}/.well-known/openid-configuration", new OpenIdConnectConfigurationRetriever());
            var openIdConfig = await configurationManager.GetConfigurationAsync(CancellationToken.None);
            var validationParameters = new TokenValidationParameters()
            {
                ValidateLifetime = true,
                ValidateAudience = false,
                ValidateIssuer = false,
                RequireSignedTokens = true,
                IssuerSigningKeys = openIdConfig.SigningKeys,
            };
            new JwtSecurityTokenHandler().ValidateToken(accessToken, validationParameters, out var validToken);
            // threw on invalid, so...
            return validToken as JwtSecurityToken;
        }
        catch (Exception ex)
        {
            logger.Info(ex.Message);
            return null;
        }
    }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.