Add support for Hub Authorize Attribute (#532)
This commit is contained in:
parent
fd7abb31e8
commit
4c4be7ed6f
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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");
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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>();
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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>();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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") }));
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue