【问题标题】:Thinktecture IdentityServer v3 with WebForms and WebApi带有 WebForms 和 WebApi 的 Thinktecture IdentityServer v3
【发布时间】:2015-04-20 03:57:44
【问题描述】:

我正在尝试一段时间来弄清楚如何使用 Thinktecture IdentityServer v3 为旧版 webforms 应用程序解决 SSO(单点登录)问题。不幸的是,我被堆叠了。

基础设施是这样的:

  • 需要身份验证和授权的 WebForm 应用程序(可能 cookie 或不记名令牌)
  • javascript 轻量级应用(一旦用户通过身份验证)向 WebApi(位于不同域中)发出请求

我有以下问题,希望能帮助我提出问题:

  1. 即使在 Web.Config 中设置,我也无法使旧版 Webforms 应用程序重定向到 IdentityServer。我在 Startup.cs 中正确设置了 app.UseCookieAuthentication(....) 和 app.UseOpenIdConnectAuthentication(....) (我猜)。对于 MVC,[Authorize] 属性强制重定向到 IdentityServer。网络表单应该如何做到这一点?
  2. 有没有办法在用户登录后将存储在 cookie 中的令牌作为承载令牌重用于从 javascript 客户端发出的 WebApi 调用。我只想代表当前登录的用户向 WebApi 发出请求(再次,webforms 应用程序和 webapi 位于不同的域中)

任何帮助将不胜感激。

谢谢!

【问题讨论】:

标签: asp.net asp.net-web-api webforms thinktecture-ident-server


【解决方案1】:

我目前正在从事同一类型的项目。这是我到目前为止所发现的。

有 4 个单独的问题。

  1. 身份服务器 - 维护身份验证用户/客户端/范围
  2. WebApi - 使用身份服务器生成的令牌用于用户的授权和身份信息。
  3. WebForms / JQuery - 我的项目目前正在处理重定向到新 WebApi 的现有功能的身份验证。
  4. 使用 Javascript 的 HTML - 严格使用 WebApi 获取信息。

下面的自定义授权适用于当前通过 WebForm 作为会员对象登录的用户,我不想再次要求用户通过 Identity Server 重新登录。

对于直接 oAuth 身份验证,请查看此处的示例。

Sample Javascript Client

将 Javascript 配置为隐式流就可以了。使用 api 保存令牌连接。

身份服务器 v3

我必须使用

进行配置

Custom Grant w IUserService

Custom Grants

这些将展示如何配置自定义授权验证。通过用户服务,您可以让身份服务查询现有用户并自定义声明。

Identity Server 有很多配置可以让它成为你自己的。这在 IdentityServer 网站上有很好的记录,我不会介绍如何设置基础知识。

例如:客户端配置

 return new List<Client>
            {
                new Client
                {
                    ClientName = "Custom Grant Client",
                    Enabled = true,

                    ClientId = "client",
                    ClientSecrets = new List<ClientSecret>
                    {
                        new ClientSecret("secret".Sha256()),
                    },

                    Flow = Flows.Custom,
                    CustomGrantTypeRestrictions = new List<string>
                    {
                        "custom"
                    }
                }
            };

WebApi - 资源

示例 WebApi Client Sample

需要有Nuget包

Thinktecture.IdentityServer.AccessTokenValidation

启动.cs

app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions
                {
                    //Location of your identity server
                    Authority = "https://localhost:44333/core"
                });

网络表单 后端 WebForms 调用

需要 Nuget 包

Thinktecture.IdentityModel.Client

    [WebMethod]
    [ScriptMethod(ResponseFormat.Json)]
    public static string AuthorizeClient()
        {
                var client = new OAuth2Client(
                //location of identity server, ClientId, ClientSecret
                new Uri("http://localhost:44333/core/connect/token"),
                "client",
                "secret");
           //ClientGrantRestriction, Scope (I have a Client Scope of read), Listing of claims
            var result = client.RequestCustomGrantAsync("custom", "read", new Dictionary<string, string>
                {
                    { "account_store", "foo" },
                    { "legacy_id", "bob" },
                    { "legacy_secret", "bob" }
                }).Result;

           return result.AccessToken;
        }

这些是本示例的通用声明,但是我可以生成自己的与用户相关的声明对象以发送到身份服务器并重新生成身份以供 WebApi 使用。

WebForms / JQuery 使用

JQuery.cookie

 $('#btnTokenCreate').click(function (e) {

        //Create Token from User Information
        Ajax({
            url: "Default.aspx/AuthorizeClient",

            type: "POST"
        },
   null,
   function (data) {
       sendToken = data.d;

       //Clear Cookie
       $.removeCookie('UserAccessToken', { path: '/' });

       //Make API Wrap Info in Stringify
       $.cookie.json = true;
       //Save Token as Cookie
       $.cookie('UserAccessToken', sendToken, { expires: 7, path: '/' });

   });

JQuery WebAPI Ajax 示例 Ajax 方法 - 注意 beforeSend。

function Ajax(options, apiToken, successCallback) {
    //Perform Ajax Call
    $.ajax({
        url: options.url,
        data: options.params,
        dataType: "json",
        type: options.type,
        async: false,
        contentType: "application/json; charset=utf-8",
        dataFilter: function (data) { return data; },
        //Before Sending Ajax Perform Cursor Switch
        beforeSend: function (xhr) {
            //Adds ApiToken to Ajax Header 
            if (apiToken) {
                xhr.withCredentials = true;
                xhr.setRequestHeader("Authorization", " Bearer " + apiToken);
            }
        },
        // Sync Results
        success: function (data, textStatus, jqXHR) {
            successCallback(data, textStatus, jqXHR);
        },
        //Sync Fail Call back
        error: function (jqXHR, textStatus, errorThrown) {
            console.log(errorThrown);
        }

    });
}

AngularJS

这与使用 JQuery 的想法相同

module.run(function($http) {

  //Make API Wrap Info in Stringify
       $.cookie.json = true;
       //Save Token as Cookie
      var token = $.cookie('UserAccessToken');
$http.defaults.headers.common.Authorization = 'Bearer ' + token });

这假设您使用与 WebForm 相同的域。否则,我将使用查询字符串重定向到带有令牌的 Angular 页面。

对于 CORS 支持,需要确保 WebApi 已为正确功能配置了 Cors。使用

Microsoft.AspNet.WebApi.Cors

希望这对如何处理这个问题有所启发

【讨论】:

  • 谢谢 Derek,但我基本上设法通过处理 SecurityTokenValidated 通知并将 AccessToken 作为声明添加到 ClaimIdentity 来做到这一点。之后,在 javascript 客户端中使用此 AccessToken 作为 Bearer 令牌是微不足道的。我还必须使用自定义 IUserService 实现来从我现有的数据库中检索和收集用户。无论如何,谢谢你的详细例子。这很有帮助。
猜你喜欢
  • 2015-05-02
  • 1970-01-01
  • 1970-01-01
  • 2014-12-26
  • 1970-01-01
  • 1970-01-01
  • 2015-03-18
  • 1970-01-01
  • 2014-08-01
相关资源
最近更新 更多