Login Login
MORE

WIDGETS

Widgets

Wanted articles
Who is online?
Article tools

Difference between revisions of "CSharp:WebAPI Varie e Tips"

From Aino Wiki

Jump to: navigation, search
(Sicurezza)
 
(No difference)

Latest revision as of 13:46, 27 September 2024

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).

La Basic Authentication consente di accedere ai metodi solo dopo autenticazione con userName e password personalizzate ed è lo strumento più semplice rispetto ad altre forme come l'autenticazione di Dominio o attraverso l'OAuth2 ( guida interna).
Web API BasicAuthentication Solution 01.png

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:

Web API BasicAuthentication PopUp.png

SSL su IIS

Link interni:

Mappa e Link


C# | WEB API


Visual Studio | MS SQL | Dizionario


Parole chiave: