【问题标题】:websockets and authentication with identityserver4websockets和身份验证与身份服务器4
【发布时间】:2017-08-25 10:26:49
【问题描述】:

我正在使用 .net core 1.1 和 identityserver 4 来获取令牌并验证用户。 Web api 可以很好地从标头中读取不记名令牌并获取用户主体声明。

现在我想使用 websocket(不是 SignalR)来发送通知。我可以打开一个 ws:// 频道(或 wss),但令牌不会随标头一起发送,因此在 .net 核心应用程序中我没有用户信息(用户声明和身份)。

如何通过 websocket 对用户进行身份验证?我进行了搜索,但找不到任何有用的信息。

谢谢

【问题讨论】:

标签: websocket asp.net-core asp.net-identity


【解决方案1】:

与WebSocket中间件中的身份验证相关的主要问题有两个:

应手动调用授权

首先,授权不适用于web socket请求(因为它不是一个可以用Authorize属性标记的控制器)。 这就是为什么在 WebSocket 中间件中您需要自己调用授权的原因。这很容易通过调用HttpContext对象的AuthenticateAsync扩展方法来实现。

因此,您的中间件将如下所示:

public class WebSocketMiddleware
{
    private readonly RequestDelegate next;
    public WebSocketMiddleware(RequestDelegate next)
    {
        this.next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        if (!context.WebSockets.IsWebSocketRequest)
        {
            await this.next.Invoke(context);
            return;
        }

        AuthenticateResult authenticateResult = 
            await context.AuthenticateAsync(OAuthValidationDefaults.AuthenticationScheme);

         ....
        });
    }

因此,使用身份验证结果,您可以检查用户是否通过身份验证,然后访问经过身份验证的用户信息。

将不记名令牌传递给网络套接字请求

对于 Web Socket 连接,默认的 Authorization 标头不起作用,因为 WebSockets JS API 不允许设置自定义参数。为了解决这个限制,访问令牌经常在查询字符串中传递。

要使身份验证中间件使用它,您需要更新身份验证验证选项。这基本上可以在您的启动脚本中完成,如下所示:

services
    .AddAuthentication()
    .AddOAuthValidation(options =>
    {
        options.Events = new OAuthValidationEvents
        {
            // Note: for Web Socket connections, the default Authorization header does not work,
            // because the WebSockets JS API doesn't allow setting custom parameters.
            // To work around this limitation, the access token is retrieved from the query string.
            OnRetrieveToken = context =>
            {
                context.Token = context.Request.Query["access_token"];
                return Task.FromResult(0);
            }
        };
    });

下面的代码可以作为例子,在连接初始化的时候给web socket url添加访问令牌:

const protocol = location.protocol === "https:" ? "wss:" : "ws:";
const wsUri = protocol + "//" + window.location.host + "/ws" + "?access_token=" + token;
this.socket = new WebSocket(wsUri);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-11
    • 2020-10-08
    • 2020-11-17
    • 1970-01-01
    相关资源
    最近更新 更多