När du har utvecklat ditt webb-API innan du exponerar det för dina kunder, kan du behöva säkra vissa eller alla delar av din API-tjänst så att endast verifierade användare kan komma åt din API-tjänst. Denna säkring i ASP.NET kan uppnås med hjälp av autentiserings- och auktorisationsmekanismerna.
Autentisering är processen att avgöra om någon eller någonting faktiskt är vem eller vad det hävdas vara. Genom att använda autentiseringsmekanismen ser vi till att alla förfrågningar som mottas av webb-API-tjänsten skickas från en klient med korrekt behörighetsuppgifter.
en meddelandehanterare är en klass som tar emot en HTTP-begäran och returnerar ett HTTP-svar. Meddelandehanterare är härledda klasser från abstraktklassen HttpMessageHandler
. De är bra för tvärgående problem som fungerar i nivå med HTTP-meddelanden (i stället för kontrolleråtgärder). Till exempel kan en meddelandehanterare:
I ett webb-API är en serie meddelandehanterare kedjda tillsammans och bildar ett mönster som heter delegera hanterare.
Ordern där dessa hanterare är inställda är viktiga eftersom de kommer att utföras sekventiellt.
Den viktigaste hanteraren sitter högst upp och skyddar allt som kommer in. Om kontrollerna passerar kommer den att överföra denna begäran nerför kedjan till nästa delegeringshandlare och så vidare.
Om allt går bra kommer det då att komma till API Controller och genomföra önskad åtgärd. Om någon av kontrollerna misslyckas inom hanteraren, nekas förfrågan och ett svar skickas till klienten.
Med den här mycket teorin i hand, låt oss nu skriva kod för våra hanterare. Vi kommer att skapa två meddelandehanterare i den här artikeln:
I ditt webb API-projekt skapar du en mapp som heter MessageHandlers
och lägg till en klass APIKeyHandler.cs
.
offentlig klass APIKeyHandler: DelegatingHandler // Ange en standard API-nyckel privat const-sträng yourApiKey = "X-some-key"; skyddad överstyrning async UppgiftSendAsync (HttpRequestMessageförfrågan, AnnulleringToken cancellationToken) bool isValidAPIKey = false; IEnumerable lsHeaders; // Bekräfta att api-nyckeln existerar var checkApiKeyExists = request.Headers.TryGetValues ("API_KEY", ut lsHeaders); om (checkApiKeyExists) if (lsHeaders.FirstOrDefault (). Equals (yourApiKey)) isValidAPIKey = true; // Om nyckeln inte är giltig, returnera en http statuskod. om (! isValidAPIKey) returnera request.CreateResponse (HttpStatusCode.Forbidden, "Bad API Key"); // Tillåt begäran att bearbeta längre ner i rörledningen var svar = vänta på base.SendAsync (begäran, avbokningToken); // Återgå svaret tillbaka till kedjans returreaktion;
De APIKeyHandler.cs
ärver från DelegatingHandler
, som i sin tur ärverver från HttpMessageHandler
. Detta gör det möjligt för oss att överstyra funktionaliteten för inspektion av en HTTP-begäran och kontrollera om vi vill tillåta den här förfrågan att flöda ner rörledningen till nästa hanterare och kontroller eller stoppa begäran genom att skicka ett anpassat svar.
I denna klass uppnår vi detta genom att överstyra SendAsync
metod. Metoden söker efter en API-nyckel (api_key
) i huvudet för varje HTTP-förfrågan och skickar endast begäran till styrenheten om en giltig API-nyckel finns i begäranhuvudet.
Nu, för att se denna handlare i åtgärd, måste vi först registrera den i vår ansökan i Application_Start
metod från Global.asax
fil.
GlobalConfiguration.Configuration.MessageHandlers.Add (ny APIKeyHandler ());
Försök att ringa någon metod som du har utsatt genom dina Web API-kontroller och du bör se "Dålig API-nyckel" som svar.
För en demo i den här artikeln använder jag samma projekt och de webbadresser som jag har skapat i min tidigare artikel, "Utveckla ett ASP.NET Web API".
Låt oss verifiera att APIKeyHandler
fungerar bra genom att skapa en HTTP-förfrågan med korrekta rubriker. För det behöver vi skapa en HTTP-rubrik med nyckelvärde:
"API_KEY": "X-some-key"
Jag använder en Mozilla-webbläsare plugin kallad "HTTP Tool" för att skapa HTTP-begäran rubriker här.
HTTP-förfrågan skickas nu hela vägen till regulatorn av handlaren.
Så vår API-nyckelchefer är nu på plats. Detta säkrar vårt webb API för att se till att endast de klienter som är försedda med giltiga API-nycklar kan komma åt den här tjänsten. Nästa kommer vi att titta på hur vi kan implementera säkerhet baserat på användarroller.
Grundläggande autentisering, som namnet antyder, är den enklaste och grundläggande formen av autentisering av HTTP-förfrågningar. Klienten skickar Base64-kodade referenser i auktoriseringsrubriken på varje HTTP-begäran, och endast om referenserna verifieras returnerar API: n det förväntade svaret. Grundläggande autentisering kräver inte serverplatsens lagringsutrymme eller implementering av cookies eftersom varje begäran är verifierad av API: n.
När förståelse för grundläggande autentisering i Web API förstås kommer det att vara mycket enkelt att koppla ihop andra former av autentisering. Endast autentiseringsprocessen kommer att vara annorlunda, och Web API-krokarna, där det är gjort, kommer att vara desamma.
För att verifiera användaruppgifter, skapar vi en IPrincipal
objekt som representerar det aktuella säkerhetskontextet.
Lägg till en ny mapp som heter säkerhet
och en ny klass TestAPIPrincipal.cs
i det.
offentlig klass TestAPIPrincipal: IPrincipal // Constructor public TestAPIPrincipal (stränganvändarnamn) UserName = userName; Identity = new GenericIdentity (användarnamn); allmän sträng Användarnamn get; uppsättning; offentliga IIdentity Identity get; uppsättning; offentlig bool IsInRole (strängroll) om (roll.Equals ("user")) return true; annars return false;
De IIdentity
objekt som är associerat med huvudmannen har en egendom som heter IsAuthenticated
. Om användaren är autentiserad kommer den här egenskapen att returneras sant; annars kommer det att returnera falskt.
Nu, låt oss skapa en annan hanterare som heter AuthHandler.cs
.
offentlig klass AuthHandler: DelegatingHandler string _userName = ""; // Metod att validera inloggningsuppgifter från behörighet // headervärde privat bool ValidateCredentials (AuthenticationHeaderValue authenticationHeaderVal) försök om (authenticationHeaderVal! = Null &&! String.IsNullOrEmpty (authenticationHeaderVal.Parameter)) string [] decodedCredentials = Encoding.ASCII.GetString (Convert.FromBase64String (authenticationHeaderVal.Parameter)) .Split (nytt [] ':'); // nu avkodadCredentials [0] kommer att innehålla // användarnamn och avkodadCredentials [1] ska // innehålla lösenord. om (avkodadCredentials [0] .Equals ("användarnamn") && decodedCredentials [1] .Equals ("password")) _userName = "John Doe"; returnera true; // request authenticated. returnera false; // request not authenticated. fånga return false; skyddad överstyrning async-uppgiftSendAsync (HttpRequestMessage request, CancellationToken cancellationToken) // om credentials valideras, // set CurrentPrincipal och Current.User if (ValidateCredentials (request.Headers.Authorization)) Thread.CurrentPrincipal = nytt TestAPIPrincipal (_userName); HttpContext.Current.User = nytt TestAPIPrincipal (_userName); // Execute base.SendAsync att utföra standard // handlingar och när det är klart, // ta emot svarobjektet och lägg till // WWW-Authenticate header om begäran // var markerad som obehörig. // Tillåt begäran att bearbeta längre ner i rörledningen var svar = vänta på base.SendAsync (begäran, avbokningToken); om (response.StatusCode == HttpStatusCode.Unauthorized &&! response.Headers.Contains ("WwwAuthenticate")) response.Headers.Add ("WwwAuthenticate", "Basic"); returrespons
Denna klass innehåller en privat metod ValidateCredentials
, som kontrollerar avkodade användarnamn och lösenordsvärden från HTTP-förfrågningshuvudet, och även SendAsync
Metod för avlyssning av HTTP-förfrågan.
Om klientens uppgifter är giltiga, så är det aktuella IPrincipal
objektet är fäst vid den aktuella tråden, dvs. Thread.CurrentPrincipal
. Vi ställer också in HttpContext.Current.User
för att göra säkerhetskontexten konsekvent. Detta gör det möjligt för oss att få tillgång till aktuella användares detaljer från var som helst i ansökan.
När begäran är autentiserad, base.SendAsync
kallas för att skicka begäran till innerhanteraren. Om svaret innehåller ett HTTP-otillåtet huvud, injicerar koden a WwwAuthenticate
rubrik med värdet Grundläggande
att informera kunden om att vår service förväntar sig grundläggande autentisering.
Nu måste vi registrera den här hanteraren i Global.asax
klass som vi gjorde för vårt ApiKeyHandler
. Se till att AuthHandler
Handler är under förstahandsregistreringen för att försäkra sig om rätt ordning.
GlobalConfiguration.Configuration.MessageHandlers.Add (ny APIKeyHandler ()); GlobalConfiguration.Configuration.MessageHandlers.Add (nya AuthHandler ());
Men innan vi kan se grundläggande autentisering i åtgärd måste vi först genomföra godkännande.
Auktorisation verifierar om den autentiserade användaren kan utföra en viss åtgärd eller konsumera en viss resurs. Denna process i Web API händer senare i rörledningen, efter
autentisering och innan kontrolleråtgärderna utförs.
ASP.NET MVC Web API tillhandahåller ett behörighetsfilter som heter AuthorizeAttribute
som verifierar begäran IPrincipal
, kontrollerar dess Identity.IsAuthenticated
egendom och returnerar a 401 Ej auktoriserad
HTTP-status om värdet är felaktigt och den begärda åtgärdsmetoden inte kommer att utföras. Detta filter kan appliceras på olika nivåer som kontrollernivå eller åtgärdsnivå och kan enkelt appliceras med hjälp av [Godkänna]
syntax ovanpå kontroller eller åtgärder.
[Tillåt] offentliga klass ClassifiedsController: ApiController
När det här attributet är inställt kommer det att förhindra att alla åtgärdsmetoder i kontrollenheten nås av obehöriga användare.
Först börjar vår grundläggande autentiseringshandlare att ställa in den aktuella användarens identitet IPrincipal
objekt. Sedan, innan denna förfrågan når kontrollenheten, AuthorizeAttribute
verifierar åtkomst till den aktuella kontrollen / åtgärden för den nuvarande användaren.
För att se detta i åtgärd, låt vi först skapa en HTTP-förfrågan utan korrekt behörighetsuppgifter.
Tillgången nekas av AuthorizeAttribute
.
Nu, låt oss skapa en annan förfrågan med auktoriseringshuvudnyckel / värdet den här gången enligt följande:
Tillstånd: Grundläggande dXNlcm5hbWU6cGFzc3dvcmQ =
Här är värdet dXNlcm5hbWU6cGFzc3dvcmQ =
ärBase64-kodad form av användarnamn Lösenord
.
Denna begäran får åtkomsträttigheter till den registeransvarige / åtgärd som förväntat.
Detta är ett exempel på att säkra hela kontrollantens offentliga åtgärder.
Vi kan också begränsa vissa delar av kontrolleråtgärderna genom att ställa in[Godkänna]
ange bara på åtgärdsnivån istället. Om vi gör det kommer vi att kunna ha både skyddade och oskyddade åtgärder i samma kontroller.
// [Godkänn] offentliga klass ClassifiedsController: ApiController public listHämta (sträng-id) return ClassifiedService.GetClassifieds (id); [Authorize] public List Få () returnera ClassifiedService.GetClassifieds ("");
Ett annat sätt att ha både skyddade och oskyddade åtgärder inom styrenheten är att använda sig av [AllowAnonymous]
attribut. När vi ställer in [Godkänna]
attribut på kontrollernivå och ställ in [AllowAnonymous]
attribut för alla åtgärder inom kontrollenheten, kommer den här åtgärden att hoppa över [Godkänna]
attribut.
Det är också möjligt att filtrera vissa roller och användare för åtkomsträttigheter. Till exempel kan vi ha något liknande [Tillåt (Roller = "Admin")]
på kontrollerna och åtgärderna.
Slutligen kan vi också skapa vårt eget anpassade attribut beroende på våra behov. Ett av sätten att uppnå detta är genom att förlänga AuthorizeAttribute
.
Säg att vi vill begränsa vår webb API-tjänst till endast vissa delar av världen genom att begränsa åtkomsten till användare som inte ligger inom ett visst intervall av IP-adress. Vi kan skapa ett anpassat behörighetsattribut för detta ändamål genom att härleda från AuthorizeAttribute
klass och övertyga IsAuthorized
metod.
public class RestrictIPsAttribute: System.Web.Http.AuthorizeAttribute skyddad överstyrning bool IsAuthorized (HttpActionContext context) var ip = HttpContext.Current.Request.UserHostAddress; // kolla efter ip här om (ip.Contains ("")) return true; returnera false;
När vi har vårt egna auktoriserat attribut kan vi dekorera våra kontroller / handlingar med den.
[BegränsaIPsAttribute] Public ListFå () returnera ClassifiedService.GetClassifieds ("");
I den här artikeln tittade vi på hur vi kan säkra vår ASP.NET Web API-tjänst innan vi exponerar tjänsten till världen utanför. Vi tittade på hur vi kan verifiera HTTP-förfrågningar om giltiga API-nycklar och för giltiga användaruppgifter. Med denna stora kunskap i hand tror jag att vi är redo att utveckla någon anpassad säkerhet för våra API: er.
För er som antingen bara börjar med Laravel eller vill utvidga din kunskap, webbplats eller ansökan med tillägg, har vi en mängd olika saker du kan studera i Envato Market.
Jag hoppas att du njöt av att läsa så mycket som att lära av den här artikeln, och kom ihåg att lämna några frågor eller kommentarer i foderet nedan!