Add support for Hub Authorize Attribute (#532)

This commit is contained in:
BrennanConroy 2017-06-06 15:46:08 -07:00 committed by GitHub
parent fd7abb31e8
commit 4c4be7ed6f
9 changed files with 31 additions and 33 deletions

View File

@ -2,13 +2,11 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
namespace ChatSample.Controllers namespace ChatSample.Controllers
{ {
public class HomeController : Controller public class HomeController : Controller
{ {
[Authorize]
public IActionResult Index() public IActionResult Index()
{ {
return View(); return View();

View File

@ -1,13 +1,11 @@
// Copyright (c) .NET Foundation. All rights reserved. // Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
namespace ChatSample.Hubs namespace ChatSample.Hubs
{ {
// TODO: Make this work
[Authorize] [Authorize]
public class Chat : HubWithPresence public class Chat : HubWithPresence
{ {
@ -18,12 +16,6 @@ namespace ChatSample.Hubs
public override async Task OnConnectedAsync() public override async Task OnConnectedAsync()
{ {
if (!Context.User.Identity.IsAuthenticated)
{
Context.Connection.Transport.Dispose();
return;
}
await Clients.Client(Context.ConnectionId).InvokeAsync("SetUsersOnline", await GetUsersOnline()); await Clients.Client(Context.ConnectionId).InvokeAsync("SetUsersOnline", await GetUsersOnline());
await base.OnConnectedAsync(); await base.OnConnectedAsync();

View File

@ -8,9 +8,7 @@ using ChatSample.Services;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.AspNetCore.SignalR; using Microsoft.AspNetCore.SignalR;
using Microsoft.AspNetCore.SignalR.Redis;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
@ -60,7 +58,7 @@ namespace ChatSample
//.AddRedis() //.AddRedis()
; ;
services.AddAuthentication(); services.AddAuthentication();
services.AddCookieAuthentication();
services.AddSingleton(typeof(DefaultHubLifetimeManager<>), typeof(DefaultHubLifetimeManager<>)); services.AddSingleton(typeof(DefaultHubLifetimeManager<>), typeof(DefaultHubLifetimeManager<>));
services.AddSingleton(typeof(HubLifetimeManager<>), typeof(DefaultPresenceHublifetimeMenager<>)); services.AddSingleton(typeof(HubLifetimeManager<>), typeof(DefaultPresenceHublifetimeMenager<>));
@ -88,9 +86,6 @@ namespace ChatSample
app.UseAuthentication(); app.UseAuthentication();
// Add external authentication middleware below. To configure them please see http://go.microsoft.com/fwlink/?LinkID=532715
//app.UseCookieAuthentication();
app.UseSignalR(routes => app.UseSignalR(routes =>
{ {
routes.MapHub<Chat>("chat"); routes.MapHub<Chat>("chat");

View File

@ -81,7 +81,7 @@ function addUserOnline(user) {
return; return;
} }
var userLi = document.createElement('li'); var userLi = document.createElement('li');
userLi.innerText = `user.Name (${user.ConnectionId})`; userLi.innerText = `${user.Name} (${user.ConnectionId})`;
userLi.id = user.ConnectionId; userLi.id = user.ConnectionId;
document.getElementById('users').appendChild(userLi); document.getElementById('users').appendChild(userLi);
} }

View File

@ -1,6 +1,9 @@
// Copyright (c) .NET Foundation. All rights reserved. // Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Reflection;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Sockets; using Microsoft.AspNetCore.Sockets;
namespace Microsoft.AspNetCore.SignalR namespace Microsoft.AspNetCore.SignalR
@ -16,7 +19,21 @@ namespace Microsoft.AspNetCore.SignalR
public void MapHub<THub>(string path) where THub : Hub<IClientProxy> public void MapHub<THub>(string path) where THub : Hub<IClientProxy>
{ {
_routes.MapSocket(path, builder => MapHub<THub>(path, socketOptions: null);
}
public void MapHub<THub>(string path, Action<HttpSocketOptions> socketOptions) where THub : Hub<IClientProxy>
{
// find auth attributes
var authorizeAttribute = typeof(THub).GetCustomAttribute<AuthorizeAttribute>();
var options = new HttpSocketOptions();
if (authorizeAttribute != null)
{
options.AuthorizationData.Add(authorizeAttribute);
}
socketOptions?.Invoke(options);
_routes.MapSocket(path, options, builder =>
{ {
builder.UseHub<THub>(); builder.UseHub<THub>();
}); });

View File

@ -30,7 +30,7 @@ namespace Microsoft.AspNetCore.Sockets
public async Task ExecuteAsync(HttpContext context, HttpSocketOptions options, SocketDelegate socketDelegate) public async Task ExecuteAsync(HttpContext context, HttpSocketOptions options, SocketDelegate socketDelegate)
{ {
if (!await AuthorizeHelper.AuthorizeAsync(context, options.AuthorizationPolicyNames)) if (!await AuthorizeHelper.AuthorizeAsync(context, options.AuthorizationData))
{ {
return; return;
} }

View File

@ -2,12 +2,13 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic; using System.Collections.Generic;
using Microsoft.AspNetCore.Authorization;
namespace Microsoft.AspNetCore.Sockets namespace Microsoft.AspNetCore.Sockets
{ {
public class HttpSocketOptions public class HttpSocketOptions
{ {
public IList<string> AuthorizationPolicyNames { get; } = new List<string>(); public IList<IAuthorizeData> AuthorizationData { get; } = new List<IAuthorizeData>();
public TransportType Transports { get; set; } = TransportType.All; public TransportType Transports { get; set; } = TransportType.All;

View File

@ -13,7 +13,7 @@ namespace Microsoft.AspNetCore.Sockets.Internal
{ {
public static class AuthorizeHelper public static class AuthorizeHelper
{ {
public static async Task<bool> AuthorizeAsync(HttpContext context, IList<string> policies) public static async Task<bool> AuthorizeAsync(HttpContext context, IList<IAuthorizeData> policies)
{ {
if (policies.Count == 0) if (policies.Count == 0)
{ {
@ -21,14 +21,8 @@ namespace Microsoft.AspNetCore.Sockets.Internal
} }
var policyProvider = context.RequestServices.GetRequiredService<IAuthorizationPolicyProvider>(); var policyProvider = context.RequestServices.GetRequiredService<IAuthorizationPolicyProvider>();
var authorizeData = new List<IAuthorizeData>();
foreach (var policy in policies) var authorizePolicy = await AuthorizationPolicy.CombineAsync(policyProvider, policies);
{
authorizeData.Add(new AuthorizeAttribute(policy));
}
var authorizePolicy = await AuthorizationPolicy.CombineAsync(policyProvider, authorizeData);
var policyEvaluator = context.RequestServices.GetRequiredService<IPolicyEvaluator>(); var policyEvaluator = context.RequestServices.GetRequiredService<IPolicyEvaluator>();

View File

@ -10,6 +10,7 @@ using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Http.Internal; using Microsoft.AspNetCore.Http.Internal;
@ -560,7 +561,7 @@ namespace Microsoft.AspNetCore.Sockets.Tests
builder.UseEndPoint<TestEndPoint>(); builder.UseEndPoint<TestEndPoint>();
var app = builder.Build(); var app = builder.Build();
var options = new HttpSocketOptions(); var options = new HttpSocketOptions();
options.AuthorizationPolicyNames.Add("test"); options.AuthorizationData.Add(new AuthorizeAttribute("test"));
// would hang if EndPoint was running // would hang if EndPoint was running
await dispatcher.ExecuteAsync(context, options, app).OrTimeout(); await dispatcher.ExecuteAsync(context, options, app).OrTimeout();
@ -598,7 +599,7 @@ namespace Microsoft.AspNetCore.Sockets.Tests
builder.UseEndPoint<TestEndPoint>(); builder.UseEndPoint<TestEndPoint>();
var app = builder.Build(); var app = builder.Build();
var options = new HttpSocketOptions(); var options = new HttpSocketOptions();
options.AuthorizationPolicyNames.Add("test"); options.AuthorizationData.Add(new AuthorizeAttribute("test"));
context.User = new ClaimsPrincipal(new ClaimsIdentity("authenticated")); context.User = new ClaimsPrincipal(new ClaimsIdentity("authenticated"));
@ -642,7 +643,7 @@ namespace Microsoft.AspNetCore.Sockets.Tests
builder.UseEndPoint<TestEndPoint>(); builder.UseEndPoint<TestEndPoint>();
var app = builder.Build(); var app = builder.Build();
var options = new HttpSocketOptions(); var options = new HttpSocketOptions();
options.AuthorizationPolicyNames.Add("test"); options.AuthorizationData.Add(new AuthorizeAttribute("test"));
// "authorize" user // "authorize" user
context.User = new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim(ClaimTypes.NameIdentifier, "name") })); context.User = new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim(ClaimTypes.NameIdentifier, "name") }));
@ -692,7 +693,7 @@ namespace Microsoft.AspNetCore.Sockets.Tests
builder.UseEndPoint<TestEndPoint>(); builder.UseEndPoint<TestEndPoint>();
var app = builder.Build(); var app = builder.Build();
var options = new HttpSocketOptions(); var options = new HttpSocketOptions();
options.AuthorizationPolicyNames.Add("test"); options.AuthorizationData.Add(new AuthorizeAttribute("test"));
// "authorize" user // "authorize" user
context.User = new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim(ClaimTypes.NameIdentifier, "name") })); context.User = new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim(ClaimTypes.NameIdentifier, "name") }));
@ -741,7 +742,7 @@ namespace Microsoft.AspNetCore.Sockets.Tests
builder.UseEndPoint<TestEndPoint>(); builder.UseEndPoint<TestEndPoint>();
var app = builder.Build(); var app = builder.Build();
var options = new HttpSocketOptions(); var options = new HttpSocketOptions();
options.AuthorizationPolicyNames.Add("test"); options.AuthorizationData.Add(new AuthorizeAttribute("test"));
// "authorize" user // "authorize" user
context.User = new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim(ClaimTypes.NameIdentifier, "name") })); context.User = new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim(ClaimTypes.NameIdentifier, "name") }));