场景
我有一个ASP.NET Web API,该API使用OAuth密码流提供承载 token 来访问其资源。
我现在正在制作需要使用此API的MVC应用程序。
计划是让MVC Controller 代表客户端浏览器对API进行调用。
来自浏览器的ajax请求将命中MVC Controller ,然后进行API调用。然后将结果作为JSON反馈给客户端,并以java-script处理。
客户端永远不要直接与API通信。
得到认证。
一旦通过成功调用Web api token 端点在MVC应用程序中收到了Bearer token ,我就需要找到处理该 token 的最佳方法。
我需要在以后对api的任何调用中使用此承载 token 。
我的计划是将其存储在System.Web.HttpContext.Current.Session["BearerToken"]
中
然后,我可以创建一个自定义AuthorizationAttribute
,该代码将检查当前HttpContext中是否存在BearerToken,如果不存在,则客户端将需要重新访问 token 端点。
这似乎可行吗?
我要求人们对此发表意见,因为我不相信这是我项目的最佳解决方案。
最佳答案
我设法提出了一些我认为效果很好的方法。
我正在使用Owin中间件进行Cookie身份验证。
在MVC应用程序中,我有一个Owin启动文件,其中配置了Cookie身份验证:-
public class Startup
{
public void Configuration(IAppBuilder app)
{
// For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=316888
app.UseCookieAuthentication(new CookieAuthenticationOptions()
{
AuthenticationType = "ApplicationCookie",
LoginPath = new PathString("/Account/Login"),
});
}
}
然后,我使用两个用于登录和注销的Action方法制作了一个AccountController:
登录。
public ActionResult Login(LoginModel model,string returnUrl)
{
var getTokenUrl = string.Format(ApiEndPoints.AuthorisationTokenEndpoint.Post.Token, ConfigurationManager.AppSettings["ApiBaseUri"]);
using (HttpClient httpClient = new HttpClient())
{
HttpContent content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("grant_type", "password"),
new KeyValuePair<string, string>("username", model.EmailAddress),
new KeyValuePair<string, string>("password", model.Password)
});
HttpResponseMessage result = httpClient.PostAsync(getTokenUrl, content).Result;
string resultContent = result.Content.ReadAsStringAsync().Result;
var token = JsonConvert.DeserializeObject<Token>(resultContent);
AuthenticationProperties options = new AuthenticationProperties();
options.AllowRefresh = true;
options.IsPersistent = true;
options.ExpiresUtc = DateTime.UtcNow.AddSeconds(int.Parse(token.expires_in));
var claims = new[]
{
new Claim(ClaimTypes.Name, model.EmailAddress),
new Claim("AcessToken", string.Format("Bearer {0}", token.access_token)),
};
var identity = new ClaimsIdentity(claims, "ApplicationCookie");
Request.GetOwinContext().Authentication.SignIn(options, identity);
}
return RedirectToAction("Index", "Home");
}
注销
public ActionResult LogOut()
{
Request.GetOwinContext().Authentication.SignOut("ApplicationCookie");
return RedirectToAction("Login");
}
保护资源
[Authorize]
public class HomeController : Controller
{
private readonly IUserSession _userSession;
public HomeController(IUserSession userSession)
{
_userSession = userSession;
}
// GET: Home
public ActionResult Index()
{
ViewBag.EmailAddress = _userSession.Username;
ViewBag.AccessToken = _userSession.BearerToken;
return View();
}
}
public interface IUserSession
{
string Username { get; }
string BearerToken { get; }
}
public class UserSession : IUserSession
{
public string Username
{
get { return ((ClaimsPrincipal)HttpContext.Current.User).FindFirst(ClaimTypes.Name).Value; }
}
public string BearerToken
{
get { return ((ClaimsPrincipal)HttpContext.Current.User).FindFirst("AcessToken").Value; }
}
}