4

我有一个带有大量 javascript 调用的 Asp.Net MVC 应用程序。我保护了一个 MVC 操作,被重定向到身份服务器,登录,然后被重定向回客户端。我可以通过 MVC 进行后续调用,但是如何获取该访问令牌并在 ajax 调用中使用它?

这是我的 Startup.cs 文件:

public void Configuration(IAppBuilder app)
{
    // Tell Microsoft to not try to map to .Net's ClaimsTypes
    JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary<string, string>();

    app.UseCookieAuthentication(new CookieAuthenticationOptions
    {
        AuthenticationType = "Cookies"
    });

    const string svcUrl = "https://localhost/svc.security";

    app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
    {
        Authority = svcUrl,
        ClientId = "nedd_client",
        RedirectUri = "http://localhost:61207/",
        ResponseType = "code id_token token",

        // Ask for 'roles' claims & for access to web services
        Scope = "openid profile",

        SignInAsAuthenticationType = "Cookies",

        Notifications = new OpenIdConnectAuthenticationNotifications
        {
            AuthorizationCodeReceived = async n =>
            {
                // filter "protocol" claims
                var claims = new List<Claim>(from c in n.AuthenticationTicket.Identity.Claims
                                             where c.Type != "iss" &&
                                                   c.Type != "aud" &&
                                                   c.Type != "nbf" &&
                                                   c.Type != "exp" &&
                                                   c.Type != "iat" &&
                                                   c.Type != "nonce" &&
                                                   c.Type != "c_hash" &&
                                                   c.Type != "at_hash"
                                             select c);

                // Get userinfo data
                var userInfoClient = new UserInfoClient(new Uri(svcUrl + "/connect/userinfo"), n.ProtocolMessage.AccessToken);

                var userInfo = await userInfoClient.GetAsync();
                userInfo.Claims.ToList().ForEach(ui => claims.Add(new Claim(ui.Item1, ui.Item2)));

                // Get access token
                var tokenClient = new OAuth2Client(new Uri(svcUrl + "/connect/token"), "nedd_client", "secret");

                var response = await tokenClient.RequestAuthorizationCodeAsync(n.Code, n.RedirectUri);

                claims.Add(new Claim("access_token", response.AccessToken));
                claims.Add(new Claim("expires_at", DateTime.Now.AddSeconds(response.ExpiresIn).ToLocalTime().ToString()));
                claims.Add(new Claim("id_token", n.ProtocolMessage.IdToken));

                n.AuthenticationTicket = new AuthenticationTicket(new ClaimsIdentity(claims.Distinct(new ClaimComparer()), n.AuthenticationTicket.Identity.AuthenticationType), n.AuthenticationTicket.Properties);
            },
        }

    });

}

这是一个示例 ajax 调用:

$.ajax({
    type: 'GET',
    url: "https://localhost/svc.security/connect/userinfo",
    //headers: { "Authorization": "Bearer " + my.getAccessToken() },   // get access token from cookie?

}).done(function (data, textStatus, jqXHR) {
    show(JSON.parse(jqXHR.response));       
4

2 回答 2

2

我意识到我真正的问题是,在登录后,cookie 是一个 ASP.Net 服务器 cookie,客户端无法访问。

我在我的 MVC 控制器中添加了一个用于 javascript 的方法来检索服务器已经拥有的令牌。

    [Authorize]
    public ActionResult GetAccessToken()
    {
        var token = (System.Web.HttpContext.Current.User.Identity as ClaimsIdentity).FindFirst("access_token");
        if (token != null)
        {
            return Content(token.Value);
        }

        return Content("");
    }

然后我的 javascript 看起来像这样,在对 web 服务进行 ajax 调用之前调用它来获取令牌。

function getAccessToken() {
    var returnVal = "";

    var xhr = new XMLHttpRequest();
    xhr.open("GET", "http://localhost:61207/Home/GetAccessToken", false);
    xhr.send();
    returnVal = xhr.responseText;

    return returnVal;
}

可能有一个更优雅的不同解决方案,但是一旦我清楚地知道客户端和服务器上可用的内容,这似乎是最好的解决方案。

于 2015-06-03T19:58:58.103 回答
1

我认为成功登录后,您应该将令牌保留在某个位置(例如在 cookie 中),然后您的“my.getAccessToken()”应该从那里读取。

这个例子类似https://github.com/IdentityServer/IdentityServer3.Samples/blob/master/source/Clients/JavaScriptImplicitClient/index.html

 if (window.location.hash) {
        handleCallback();
    }
于 2015-06-03T07:39:05.710 回答