Difference between revisions of "CSharp:WebAPI Varie e Tips"
From Aino Wiki
(→Sicurezza) |
(No difference)
|
Latest revision as of 13:46, 27 September 2024
Contents
Ambito
Percorsi e risorse
- Per avere la cartella sul server dove stà girando l'applicazione web usare:
HttpRuntime.AppDomainAppPath
- In una HTTP request, si puà avere il path della risorsa corrente con:
Server.MapPath("~/Whatever")
Content Response
Ci si riferisce alla tipologia di quanto verrà restituito in output dal metodo della WebAPI.
Fonte stackoverflow.com Generalmente potrà andar bene restituire un output "formattato" ovvero secondo un determinato mine type
, pertanto potrebbe andare benissimo Request.CreateResponse()
, questo metodo costruirà un opportuno heder automaticamente ma in casi particolare non andrà bene.
Standard
Risorse premessa:
[DataContract] public class MioResponseOutput { [DataMember] public string CampoUno { get; set; } [DataMember] public string CampoDue { get; set; } }
Quindi si restituirà in output un JSON:
using System.Net.Http; //... //Metodo Get [System.Web.Http.Route("ivr_donate")] [HttpGet] public HttpResponseMessage Donate(string parametro1) { HttpResponseMessage response = new HttpResponseMessage(); MioResponseOutput objOut = new MioResponseOutput(); //Oggetto da serializzare in uscita: Json/XML/etc //... response = Request.CreateResponse(statusCode, objOut); response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); //... return response; }
Caso particolare
Premessa vedere come è fatto l'oggetto MioResponseOutput
definito nell'esempio precedente.
Se volessimo poter scegliere tra un Output JSON e testuale (senza TAG):
using System.Net.Http; //... public enum EnumRespContentType { JSON = 0, TEXT_Custom = 1 } //... //Metodo Get [System.Web.Http.Route("ivr_donate")] [HttpGet] public HttpResponseMessage Donate(string parametro1) { MioResponseOutput objOut = new MioResponseOutput(); //... response = CreateCustomResponse(HttpStatusCode.OK, objOut, EnumRespContentType.TEXT_Custom); //... return response; } //Metodo che crea la Response adeguata private HttpResponseMessage CreateCustomResponse(HttpStatusCode statusCode , MioResponseOutput objOut , EnumRespContentType custContentType) { HttpResponseMessage response = new HttpResponseMessage(); switch (custContentType) { case EnumRespContentType.JSON: response = Request.CreateResponse(statusCode, objOut); response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); break; case EnumRespContentType.TEXT_Custom: string strResultOutput = string.Format("{0}\r\n{1}", objOut.CampoUno, objOut.CampoDue); response = new HttpResponseMessage(statusCode); response.Content = new StringContent(strResultOutput, System.Text.Encoding.UTF8, "text/plain"); //Il seguente creerebbe comunque un XML in uscita! //response = Request.CreateResponse(statusCode, resultOutput); //response.Content.Headers.ContentType = new MediaTypeHeaderValue("text/plain"); break; } return response; }
Sicurezza
Premessa
La configurazione dell'identità con cui l'applicazione su IIS può semplicemente quella di default ovvero "ApplicationPoolIdentity" (che è utenza virtuale) oppure se devono essere eseguite determinate azioni quindi con particolari permessi si può cambiare identità ad esempio con utenza specifica di Sistema Operativo.
Per info: learn.microsoft.com
Basic Authentication
Premesso che ha un senso solo se si usa l'HTTPS per proteggere, criptandole, le credenziali di accesso. Ciò è ottenibile mediante la certificazione SSL (Secure Sockets Layer).
Aggiungere un filtro
Aggiungere la cartella "Filters" e la classe BasicAuthenticationAttribute che deve ereditare da AuthorizationFilterAttribute:
using NLog; using System; using System.Collections.Generic; using System.Configuration; using System.Linq; using System.Net; using System.Net.Http; using System.Security.Principal; using System.Text; using System.Threading; using System.Web; using System.Web.Http.Controllers; using System.Web.Http.Filters; namespace WA_DigitalkBotCampaign.Filters { public class BasicAuthenticationAttribute : AuthorizationFilterAttribute { private static Logger m_logger = LogManager.GetCurrentClassLogger(); private static string m_Auth_UserName { get { return ConfigurationManager.AppSettings["Auth_UserName"].ToString(); } } private static string m_Auth_Password { get { return ConfigurationManager.AppSettings["Auth_Password"].ToString(); } } public override void OnAuthorization(HttpActionContext actionContext) { string strMessage = "Attempting to login"; string userName = string.Empty; string password = string.Empty; try { // Se non è una connessione HTTPS esce restituendo un errore if (actionContext.Request.RequestUri.Scheme != Uri.UriSchemeHttps) { actionContext.Response = new HttpResponseMessage(System.Net.HttpStatusCode.Forbidden) { ReasonPhrase = "HTTPS Required" }; m_logger.Debug("Connection refused because not HTTPS!"); } else { m_logger.Debug(strMessage); var authHeader = actionContext.Request.Headers.Authorization; if (authHeader != null) { var authenticationToken = actionContext.Request.Headers.Authorization.Parameter; var decodedAuthenticationToken = Encoding.UTF8.GetString(Convert.FromBase64String(authenticationToken)); var usernamePasswordArray = decodedAuthenticationToken.Split(':'); userName = usernamePasswordArray[0]; password = usernamePasswordArray[1]; // Replace this with your own system of security / means of validating credentials var isValid = userName == m_Auth_UserName && password == m_Auth_Password; if (isValid) { var principal = new GenericPrincipal(new GenericIdentity(userName), null); Thread.CurrentPrincipal = principal; //Riscrive la response ma non farebbe vedere l'output del metodo del controller //actionContext.Response = // actionContext.Request.CreateResponse(HttpStatusCode.OK, strMessage); strMessage = "User " + userName + " successfully authenticated"; m_logger.Info(strMessage); return; //OK uscita! } } HandleUnathorized(actionContext); } } catch (Exception ex) { strMessage = string.Format("Login for User {0} failed.\r\n{1}", userName, ex.Message); m_logger.Error(strMessage); HandleUnathorized(actionContext); } } private static void HandleUnathorized(HttpActionContext actionContext) { string strMessage = "Unathorized access!"; actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized); actionContext.Response.Headers.Add("WWW-Authenticate", "Basic Scheme='Data' location = 'http://localhost:"); m_logger.Error(strMessage); } } }
Poiché le credenziali sono incapsulate nel file di configurazione dell'applicazione (web.config) occorrerà di conseguenza aggiornarlo come segue:
<?xml version="1.0"?> <configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"> <!-- ********** Per la Basic Authentication ********** --> <appSettings> <add key="Auth_UserName" value="webAPIUserNAme" /> <add key="Auth_Password" value="PasswordWebAPI" /> </appSettings> <!-- ********** --> </configuration>
A questo punto nel controller da proteggere con l'autenticazione aggiungere il predicato [RequireHttps] a ciascuna Action.
using NLog; using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using System.Net.Http.Headers; using System.Web.Http; using System.Web.Mvc; using WA_DigitalkBotCampaign.Filters; using WA_DigitalkBotCampaign.Models; namespace WA_DigitalkBotCampaign.Controllers { [BasicAuthentication] //Per la BasicAuthentication definita in: BasicAuthenticationAttribute public class BotCampaignController : ApiController { [RequireHttps] //Per forzare l'uso della connessione HTTPS! [System.Web.Http.Route("integrations/BotCampaign/SetCampaign_VF")] public HttpResponseMessage SetCampaign_VF(SetCampaignIN infoCampaignIn) { //Bla Bla } //Bla Bla } }
Imporre il filtro di autenticazione
Quindi imporre nella classe di configurazione della Web API l'uso del filtro per la BasicAuthentication con riferimento alla classe precedentemente creata.
using System; using System.Collections.Generic; using System.Linq; using System.Web.Http; using WA_DigitalkBotCampaign.Filters; namespace WA_DigitalkBotCampaign { public static class WebApiConfig { public static void Register(HttpConfiguration config) { // Web API configuration and services // Web API routes config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute( name: "DefaultApi", //ex.: routeTemplate: "api/{controller}/{id}", //Per le GET routeTemplate: "Digitalk/integrations/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); //Autenticazione Basic della Web API config.Filters.Add(new BasicAuthenticationAttribute()); } } }
Dopo di ché accedendo a qualsiasi metodo della Web API chiederà prima l'autenticazione:
SSL su IIS
Link interni:
Mappa e Link
Visual Studio | MS SQL | Dizionario
Parole chiave: