授权不在ASP.NET Core 2.1的Signalr中工作

时间:2018-03-28 13:32:16

标签: asp.net-core asp.net-core-2.0 asp.net-core-webapi asp.net-core-signalr asp.net-core-2.1

我已按照this tutorial将我的项目从ASP.Net Core 2.0升级到ASP.NET Core 2.1。

在我将Signar Core 2.1应用到我的项目之前,一切都很好。

这是我的public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddSingleton<IAuthorizationHandler, SolidAccountRequirementHandler>(); services.AddCors( options => options.AddPolicy("AllowCors", builder => { builder .AllowAnyOrigin() .AllowCredentials() .AllowAnyHeader() .AllowAnyMethod(); }) ); services.AddAuthorization(x => { x.AddPolicy("MainPolicy", builder => { builder.Requirements.Add(new SolidAccountRequirement()); }); }); services.AddSignalR(); #region Mvc builder var authenticationBuilder = services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme); authenticationBuilder.AddJwtBearer(o => { // You also need to update /wwwroot/app/scripts/app.js o.SecurityTokenValidators.Clear(); // Initialize token validation parameters. var tokenValidationParameters = new TokenValidationParameters(); tokenValidationParameters.ValidAudience = "audience"; tokenValidationParameters.ValidIssuer = "issuer"; tokenValidationParameters.IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("SigningKey")); tokenValidationParameters.ValidateLifetime = false; o.TokenValidationParameters = tokenValidationParameters; }); // Construct mvc options. services.AddMvc(mvcOptions => { ////only allow authenticated users var policy = new AuthorizationPolicyBuilder() .RequireAuthenticatedUser() .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme) .AddRequirements(new SolidAccountRequirement()) .Build(); mvcOptions.Filters.Add(new AuthorizeFilter(policy)); }) .AddJsonOptions(options => { options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); }) .SetCompatibilityVersion(CompatibilityVersion.Version_2_1); ; #endregion } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseHsts(); } //app.UseHttpsRedirection(); app.UseCors("AllowCors"); app.UseSignalR(routes => { routes.MapHub<ChatHub>("/chathub"); }); app.UseMvc(); } }

SolidRequirementHandler

这是我的public class SolidAccountRequirementHandler : AuthorizationHandler<SolidAccountRequirement> { protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, SolidAccountRequirement requirement) { context.Succeed(requirement); return Task.CompletedTask; } }

ChatHub.cs

这是我的public class ChatHub : Hub { [Authorize(Policy = "MainPolicy")] public override Task OnConnectedAsync() { return base.OnConnectedAsync(); } }

MainPolicy

当我使用AngularJS应用程序连接到ChatHub时,我会调用OnConnectedAsync()。但是,在不检查请求标识的情况下调用了--nofetch函数。

MVC Controller的政策已经成功应用,但信号员并没有。

有人可以帮我吗?

谢谢,

2 个答案:

答案 0 :(得分:2)

我将此问题发布到Signalr github issue page。 这是他们给我的答案。 我试过,它成功地运作了:

解决方案是将[Authorize]属性放到ChatHub

[Authorize(Policy = "MainPolicy")]
public class ChatHub : Hub
{
    public override Task OnConnectedAsync()
    {
        return base.OnConnectedAsync();
    }
}

分享给谁不知道:)

答案 1 :(得分:2)

我有同样的问题,有四个关键问题:

1-在您的Startup.cs中,请注意import com.amazonaws.AmazonServiceException; import com.amazonaws.SdkClientException; import com.amazonaws.auth.AWSStaticCredentialsProvider; import com.amazonaws.auth.BasicAWSCredentials; import com.amazonaws.regions.Regions; import com.amazonaws.services.s3.AmazonS3; import com.amazonaws.services.s3.AmazonS3ClientBuilder; import com.amazonaws.services.s3.model.ObjectMetadata; import com.amazonaws.services.s3.model.PutObjectRequest; import java.io.File; import java.io.IOException; public class UploadObject { public static void main(String[] args) throws IOException { Regions clientRegion = Regions.US_EAST_1; String fileObjKeyName = "N.pdf"; String fileName = "C:\\home\\aws\\N.pdf"; //To Test the File Upload String accessKeyId = "AKIAZGSMNGVXXXZ73VXE"; String secretAccessKey = "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"; String bucketName = "fioprod-s3-addon-us-east-12"; try { final BasicAWSCredentials basicAWSCredentials = new BasicAWSCredentials(accessKeyId, secretAccessKey); //This code expects that you have AWS credentials set up per: // https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/setup-credentials.html AmazonS3 s3Client = AmazonS3ClientBuilder.standard() .withRegion(clientRegion) .withCredentials(new AWSStaticCredentialsProvider(basicAWSCredentials)) .build(); // Upload a file as a new object with ContentType and title specified. PutObjectRequest request = new PutObjectRequest(bucketName, fileObjKeyName, new File(fileName)); ObjectMetadata metadata = new ObjectMetadata(); metadata.setContentType("plain/text"); metadata.addUserMetadata("title", "someTitle"); request.setMetadata(metadata); s3Client.putObject(request); } catch (AmazonServiceException e) { // The call was transmitted successfully, but Amazon S3 couldn't process // it, so it returned an error response. e.printStackTrace(); } catch (SdkClientException e) { // Amazon S3 couldn't be contacted for a response, or the client // couldn't parse the response from Amazon S3. e.printStackTrace(); } } }

中的此顺序
Configure(IApplicationBuilder app)

app.UseRouting(); app.UseAuthorization( ); app.UseEndpoints(endpoints => { endpoints.MapHub<myChat>("/chat"); }); 应该始终在app.UseAuthorization( );app.UseRouting();之间。

2- SignalR不在标头中发送令牌,但在查询中发送令牌。在app.UseEndpoints()内的startup.cs中,您必须配置应用程序,以从查询中读取令牌并将其放入标头中。您可以通过以下方式配置JWT:

ConfigureServices(IServiceCollection services)

3-您的客户端要建立连接时应发送令牌。您可以在建立连接时向Query添加令牌。

  services.AddAuthentication()
            .AddJwtBearer(options =>
            {
                options.RequireHttpsMetadata = false;
                options.SaveToken = true;
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateAudience = false,
                    ValidIssuer = [Issuer Site],
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes([YOUR SECRET KEY STRING]))
                };
                options.Events = new JwtBearerEvents
                {
                    OnMessageReceived = context =>
                    {
                        var path = context.Request.Path;
                        var accessToken = context.Request.Query["access_token"];
                        if (!string.IsNullOrEmpty(accessToken) && path.StartsWithSegments("/chat"))
                        {
                            
                            context.Request.Headers.Add("Authorization", new[] { $"Bearer {accessToken}" });
                        }
                        return Task.CompletedTask;
                    }
                };
            });

4-我没有在var connection = new signalR.HubConnectionBuilder().withUrl( "http://localhost:5000/chat", { skipNegotiation: true, transport: signalR.HttpTransportType.WebSockets, accessTokenFactory: () => "My Token Is Here"}).build(); 内添加默认的Athuentication方案 因此,每次我必须指定这样的授权方案。 services.AddAuthentication() 最后,您可以像这样保护您的聊天类

 [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]

看来,使用语句很重要,因此请确保使用正确的语句。 SignalR hub Authorize attribute doesn't work

注意:我只对using Microsoft.AspNetCore.SignalR; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authentication.JwtBearer; [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] public class myChat : Hub { ///Some functions } 类中的单个方法进行授权存在问题。我不知道为什么。