2015-05-29 99 views
4

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

这是我的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));  
+0

难道你不能只存储在Web浏览器上的本地存储访问令牌?访问令牌不需要保密。如果它被篡改的话,它会被阻止被接受。 – webworm

回答

1

我想登录成功后,你应该保持令牌一些地方(在饼干例如),那么你的“my.getAccessToken()”应该从那里读取。

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

if (window.location.hash) { 
     handleCallback(); 
    } 
+0

Haz,适用于纯JavaScript应用程序,但不适用于混合使用MVC和ajax。我想清楚了,并在下面发布了我自己的答案。 –

+0

了解您的修补程序。它可以工作,但应该提高效率,因为每次主要请求之前都需要额外的请求。抱歉,由于我的“积分”,我无法评论您的答案;) – hazjack

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看起来是这样的,调用它获取令牌之前,使ajax调用Web服务。

function getAccessToken() { 
    var returnVal = ""; 

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

    return returnVal; 
} 

可能有不同的解决方案,更优雅,但一旦我脑子里想的是什么可以在客户端和服务器清楚,这似乎是最好的解决方案。

相关问题