SignalR与自定义身份验证和授权

huangapple go评论65阅读模式
英文:

SignalR with custom Authentication and authorization

问题

我有三个应用程序。

1)Windows 应用程序

2)Asp.net 网页表单

3)Asp.net MVC

我有一个使用 Web 服务实现的身份验证和授权系统。简单来说,底层表格如下:

 用户表:

     Id        用户名       密码       
     ---------------------------------

 角色表;
    
     Id          角色名
     ---------------------------------

 用户角色

     用户 Id        角色 Id
     ---------------------------------

现在我想为这些应用程序实现聊天功能。我的问题是我不知道如何将 SignalR 与我的自定义身份验证集成。考虑这种情况,用户想要向另一个用户发送消息:

public async Task SendMessage(string user1, string user2, string message)

这个方法乍看起来可以工作。但是如何防止这种情况发生呢:

如果 user3 知道 user1 的用户名并创建请求,从 user1 发送消息给 user2

由于我无法更改我的身份验证服务来使用 Asp.net Identity 并将其与 SignalR 集成,我怎么能确保登录的用户发送消息而没有人能够模拟?

有人能帮我得到正确的想法和计划吗?

谢谢

英文:

I have Three applications.

1)Windows Application

2)Asp.net web form

3)Asp.net MVC

I have a Authentication and Authorization system that implemented using a web service. In simple form the underlying tables are like:

 User Table:

     Id        UserName       Password       
     ---------------------------------

 Role Table;
    
     Id          RoleName
     ---------------------------------

 UserRole

     UserId        RoleId
     ---------------------------------

Now I want to implement a chat capability for these apps. My problem is I don't know how to integrate SignalR with my custom authentication. Consider this scenario that a user wants to send a message to another user:

public async Task SendMessage(string user1, string user2, string message)

this method works find in first glance. But how can I prevent this scenario:

>if user3 knows user1 username and create a request and send a message from user1 to user2?

Since I can't change my auth service to user Asp.net Identity and integrate it with SignalR How can I be sure that the logged in user send the message and no one can do impersonation?

Could any body help me to get the correct idea and plan?

Thanks

答案1

得分: 2

你有不同类型的客户端应用程序。所以我建议使用令牌(Bearer token)进行身份验证。客户端应用程序应该在发送到服务器的请求中添加一个令牌。我不知道你使用的是哪个版本的.NET,但使用.NET Core 进行配置很容易。

在Web应用中:

this.connection = new signalR.HubConnectionBuilder()
    .withUrl("/hubs/chat", { accessTokenFactory: () => this.loginToken })
    .build();

在Windows应用中:

var connection = new HubConnectionBuilder()
    .WithUrl("https://example.com/chathub", options =>
    { 
        options.AccessTokenProvider = () => Task.FromResult(_myAccessToken);
    })
    .Build();

请注意,身份服务器应该向客户端提供令牌。我看到你已经实现了自己的身份服务器。在这种情况下,使用内置库如Microsoft.AspNetCore.Identity和Entityframework Core会更加方便。另外,使用IdentityServer也是一个选择。否则,你需要实现和开发自定义的IdentityServer来向客户端提供访问令牌。

ASP.NET Core SignalR中的身份验证和授权

使用IdentityServer

在C# .NET中创建和验证JWT令牌

英文:

You have different kind of client application. So I recommend to use Bearer token for authentication. The client app should add a bearer token to the request that send to the server. I don't know which version of .net do you use but it is easy to configure using .net core.

In web app:

this.connection = new signalR.HubConnectionBuilder()
    .withUrl("/hubs/chat", { accessTokenFactory: () => this.loginToken })
    .build();

In the Windows app

var connection = new HubConnectionBuilder()
    .WithUrl("https://example.com/chathub", options =>
    { 
        options.AccessTokenProvider = () => Task.FromResult(_myAccessToken);
    })
    .Build();

Note that the identity server should provide the token to the client. I see you implemented your identity server. Using the built-in library like Microsoft.AspNetCore.Identity and Entityframework Core would have made life easier in this case. Also using IdentityServer is an option. Otherwise you need to implement and develop your custom IdentityServer that provide access token to clients.

Authentication and authorization in ASP.NET Core SignalR

Using IdentityServer

Creating And Validating JWT Tokens In C# .NET

答案2

得分: 1

你可以实现一个自定义的授权属性,在这里进行必要的检查,并拒绝未经授权的用户/接受经授权的用户。然后,你可以使用自定义授权属性装饰所需的信号中心类/方法。

你可以在这个类似问题的答案中找到有帮助的信息:https://stackoverflow.com/a/14343581/19214431。

英文:

You can implement a custom authorization attribute where you do the necessary checks and reject unauthorised users /accept authorised users. You could then decorate the desired hub classes/methods with the custom authorization attribute.

You should find this answer to a similar question helpful: https://stackoverflow.com/a/14343581/19214431.

答案3

得分: 1

不要翻译代码部分。

我不知道你使用的是哪个版本的.NET,但我尝试使用.NET Core 6。

你可以尝试使用 上下文对象 (The Context object),因为它可以获取连接的唯一ID,由SignalR分配。每个连接都有一个连接ID。链接地址

我尝试保存ID和消息,然后判断项目中是否存在该键。

你可以尝试确保使用唯一ID来保证只有已登录的用户可以发送消息,而其他人无法冒充。

ChatHub.cs文件中,代码如下:

public class ChatHub : Hub
{
    public async Task SendMessage(string user, string message)
    {
        string getID = Context.ConnectionId;
        DateTime time = DateTime.Now;

        var data = Context.Items.Where(o => o.Key == getID).ToList();
        int dataCount = Context.Items.Count();
        if (dataCount == 0)
        {
            Context.Items.Add(getID, time);
        }
        else
        {
            Context.Abort(); //中止连接
            //你的代码
        }

        await Clients.All.SendAsync("ReceiveMessage", user, message);
    }
}
英文:

I don't know which version of .net you use
but I try .net core 6.

you can try is The Context object
because Gets the unique ID for the connection, assigned by SignalR. There's one connection ID for each connection.<br>
https://learn.microsoft.com/en-us/aspnet/core/signalr/hubs?view=aspnetcore-6.0
<br>

I try to Save the ID and message then judge if the Items have key is ok.
<br>
you can try unique ID be sure that the logged-in user sends the message and no one can do an impersonation.

ChatHub.cs

 public class ChatHub : Hub
    {
        public async Task SendMessage(string user, string message)
        {
            string getID = Context.ConnectionId;
            DateTime time=DateTime.Now;

            var data = Context.Items.Where(o =&gt; o.Key == getID).ToList();
            int dataCount = Context.Items.Count();
            if (dataCount==0)
            {
                Context.Items.Add(getID,time);
            }else{
                Context.Abort();//Aborts the connection.
                 //you code
            }

         await Clients.All.SendAsync(&quot;ReceiveMessage&quot;, user, message);

        }


    }

huangapple
  • 本文由 发表于 2023年2月16日 04:01:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/75464893.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定