Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
di Patrick Fletcher, Tom FitzMacken
Avvertimento
Questa documentazione non è per la versione più recente di SignalR. Dai un'occhiata a ASP.NET Core SignalR.
Questo argomento descrive come limitare gli utenti o i ruoli che possono accedere ai metodi dell'hub.
Informazioni generali
Questo argomento contiene le sezioni seguenti:
Autorizzare l'attributo
SignalR fornisce l'attributo Authorize per specificare quali utenti o ruoli hanno accesso a un hub o a un metodo. Questo attributo si trova nello spazio dei nomi Microsoft.AspNet.SignalR. L'attributo Authorize viene applicato a un hub o a metodi specifici in un hub. Quando si applica l'attributo Authorize a una classe hub, il requisito di autorizzazione specificato viene applicato a tutti i metodi nell'hub. Di seguito sono riportati i diversi tipi di requisiti di autorizzazione che è possibile applicare. Senza l'attributo Authorize , tutti i metodi pubblici nell'hub sono disponibili per un client connesso all'hub.
Se è stato definito un ruolo denominato "Admin" nell'applicazione Web, è possibile specificare che solo gli utenti di tale ruolo possono accedere a un hub con il codice seguente.
[Authorize(Roles = "Admin")]
public class AdminAuthHub : Hub
{
}
In alternativa, è possibile specificare che un hub contiene un metodo disponibile per tutti gli utenti e un secondo metodo disponibile solo per gli utenti autenticati, come illustrato di seguito.
public class SampleHub : Hub
{
public void UnrestrictedSend(string message){ . . . }
[Authorize]
public void AuthenticatedSend(string message){ . . . }
}
Gli esempi seguenti illustrano diversi scenari di autorizzazione:
-
[Authorize]– solo utenti autenticati -
[Authorize(Roles = "Admin,Manager")]: solo gli utenti autenticati nei ruoli specificati -
[Authorize(Users = "user1,user2")]: solo gli utenti autenticati con i nomi utente specificati -
[Authorize(RequireOutgoing=false)]: solo gli utenti autenticati possono richiamare l'hub, ma le chiamate dal server ai client non sono limitate dall'autorizzazione, ad esempio quando solo determinati utenti possono inviare un messaggio, ma tutti gli altri possono ricevere il messaggio. La proprietà RequireOutgoing può essere applicata solo all'intero hub, non ai singoli metodi all'interno dell'hub. Quando RequireOutgoing non è impostato su false, solo gli utenti che soddisfano il requisito di autorizzazione vengono chiamati dal server.
Richiedere l'autenticazione per tutti gli hub
È possibile richiedere l'autenticazione per tutti gli hub e i metodi hub nell'applicazione chiamando il metodo RequireAuthentication all'avvio dell'applicazione. È possibile usare questo metodo quando si hanno più hub e si vuole applicare un requisito di autenticazione per tutti. Con questo metodo non è possibile specificare il ruolo, l'utente o l'autorizzazione in uscita. È possibile specificare che l'accesso ai metodi hub è limitato agli utenti autenticati. Tuttavia, è comunque possibile applicare l'attributo Authorize agli hub o ai metodi per specificare requisiti aggiuntivi. Qualsiasi requisito specificato negli attributi viene applicato oltre al requisito di base dell'autenticazione.
L'esempio seguente mostra un file Global.asax che limita tutti i metodi hub agli utenti autenticati.
public class Global : HttpApplication
{
void Application_Start(object sender, EventArgs e)
{
RouteTable.Routes.MapHubs();
GlobalHost.HubPipeline.RequireAuthentication();
}
}
Se si chiama il metodo dopo l'elaborazione RequireAuthentication() di una richiesta SignalR, SignalR genererà un'eccezione InvalidOperationException . Questa eccezione viene generata perché non è possibile aggiungere un modulo all'hubPipeline dopo che la pipeline è stata richiamata. Nell'esempio precedente, la chiamata al metodo RequireAuthentication nel metodo Application_Start mostra che questo viene eseguito una volta prima di gestire la prima richiesta.
Autorizzazione personalizzata
Se è necessario personalizzare la modalità di determinazione dell'autorizzazione, è possibile creare una classe che deriva da AuthorizeAttribute ed eseguire l'override del metodo UserAuthorized . Questo metodo viene chiamato per ogni richiesta per determinare se l'utente è autorizzato a completare la richiesta. Nel metodo sovrascritto, fornisci la logica necessaria per il tuo scenario di autorizzazione. L'esempio seguente illustra come applicare l'autorizzazione tramite l'identità basata sulle attestazioni.
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
public class AuthorizeClaimsAttribute : AuthorizeAttribute
{
protected override bool UserAuthorized(System.Security.Principal.IPrincipal user)
{
if (user == null)
{
throw new ArgumentNullException("user");
}
var principal = (ClaimsPrincipal)user;
if (principal != null)
{
Claim authenticated = principal.FindFirst(ClaimTypes.Authentication);
return authenticated.Value == "true" ? true : false;
}
else
{
return false;
}
}
}
Passare le informazioni di autenticazione ai client
Potrebbe essere necessario usare le informazioni di autenticazione nel codice eseguito nel client. Le informazioni necessarie vengono passate quando si chiamano i metodi nel client. Ad esempio, un metodo dell'applicazione di chat può passare come parametro il nome utente della persona che pubblica un messaggio, come illustrato di seguito.
public Task SendChatMessage(string message)
{
string name;
var user = Context.User;
if (user.Identity.IsAuthenticated)
{
name = user.Identity.Name;
}
else
{
name = "anonymous";
}
return Clients.All.addMessageToPage(name, message);
}
In alternativa, è possibile creare un oggetto per rappresentare le informazioni di autenticazione e passare tale oggetto come parametro, come illustrato di seguito.
public class SampleHub : Hub
{
public override Task OnConnected()
{
return Clients.All.joined(GetAuthInfo());
}
protected object GetAuthInfo()
{
var user = Context.User;
return new
{
IsAuthenticated = user.Identity.IsAuthenticated,
IsAdmin = user.IsInRole("Admin"),
UserName = user.Identity.Name
};
}
}
Non passare mai l'ID di connessione di un client ad altri client, perché un utente malintenzionato potrebbe usarlo per simulare una richiesta da tale client.
Opzioni di autenticazione per i client .NET
Quando si dispone di un client .NET, ad esempio un'app console, che interagisce con un hub limitato agli utenti autenticati, è possibile passare le credenziali di autenticazione in un cookie, l'intestazione di connessione o un certificato. Negli esempi di questa sezione viene illustrato come usare questi diversi metodi per l'autenticazione di un utente. Non sono app SignalR completamente funzionali. Per altre informazioni sui client .NET con SignalR, vedere Guida all'API hub - Client .NET.
Biscotto
Quando il client .NET interagisce con un hub che usa ASP.NET Autenticazione basata su form, è necessario impostare manualmente il cookie di autenticazione nella connessione. Aggiungere il cookie alla CookieContainer proprietà nell'oggetto HubConnection . Nell'esempio seguente viene illustrata un'app console che recupera un cookie di autenticazione da una pagina Web e lo aggiunge alla connessione. L'URL https://www.contoso.com/RemoteLogin nell'esempio punta a una pagina Web da creare. La pagina recupera il nome utente e la password inseriti e tenta di accedere all'utente con le credenziali.
class Program
{
static void Main(string[] args)
{
var connection = new HubConnection("http://www.contoso.com/");
Cookie returnedCookie;
Console.Write("Enter user name: ");
string username = Console.ReadLine();
Console.Write("Enter password: ");
string password = Console.ReadLine();
var authResult = AuthenticateUser(username, password, out returnedCookie);
if (authResult)
{
connection.CookieContainer = new CookieContainer();
connection.CookieContainer.Add(returnedCookie);
Console.WriteLine("Welcome " + username);
}
else
{
Console.WriteLine("Login failed");
}
}
private static bool AuthenticateUser(string user, string password, out Cookie authCookie)
{
var request = WebRequest.Create("https://www.contoso.com/RemoteLogin") as HttpWebRequest;
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.CookieContainer = new CookieContainer();
var authCredentials = "UserName=" + user + "&Password=" + password;
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(authCredentials);
request.ContentLength = bytes.Length;
using (var requestStream = request.GetRequestStream())
{
requestStream.Write(bytes, 0, bytes.Length);
}
using (var response = request.GetResponse() as HttpWebResponse)
{
authCookie = response.Cookies[FormsAuthentication.FormsCookieName];
}
if (authCookie != null)
{
return true;
}
else
{
return false;
}
}
}
L'app console pubblica le credenziali su www.contoso.com/RemoteLogin, il quale potrebbe riferirsi a una pagina vuota contenente il seguente file di code-behind.
using System;
using System.Web.Security;
namespace SignalRWithConsoleChat
{
public partial class RemoteLogin : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string username = Request["UserName"];
string password = Request["Password"];
bool result = Membership.ValidateUser(username, password);
if (result)
{
FormsAuthentication.SetAuthCookie(username, false);
}
}
}
}
Autenticazione di Windows
Quando si usa l'autenticazione di Windows, è possibile passare le credenziali dell'utente corrente usando la proprietà DefaultCredentials . Le credenziali per la connessione vengono impostate sul valore di DefaultCredentials.
class Program
{
static void Main(string[] args)
{
var connection = new HubConnection("http://www.contoso.com/");
connection.Credentials = CredentialCache.DefaultCredentials;
connection.Start().Wait();
}
}
Intestazione di connessione
Se l'applicazione non usa cookie, è possibile passare le informazioni utente nell'intestazione di connessione. Ad esempio, è possibile passare un token nell'intestazione di connessione.
class Program
{
static void Main(string[] args)
{
var connection = new HubConnection("http://www.contoso.com/");
connection.Headers.Add("myauthtoken", /* token data */);
connection.Start().Wait();
}
}
Nell'hub, dovresti quindi verificare il token dell'utente.
Certificato
È possibile passare un certificato client per verificare l'utente. Il certificato viene aggiunto durante la creazione della connessione. Nell'esempio seguente viene illustrato solo come aggiungere un certificato client alla connessione; non mostra l'app console completa. Usa la classe X509Certificate che offre diversi modi per creare il certificato.
class Program
{
static void Main(string[] args)
{
var connection = new HubConnection("http://www.contoso.com/");
connection.AddClientCertificate(X509Certificate.CreateFromCertFile("MyCert.cer"));
connection.Start().Wait();
}
}