从Web API在MVC中存储Bearer Token的位置

Der*_*rek 18 c# security session asp.net-mvc-5 asp.net-web-api2

脚本

我有一个ASP.NET Web API,它使用OAuth密码流来提供承载令牌以获取对其资源的访问权限.

我现在正在制作一个需要使用此API的MVC应用程序.

计划是让MVC控制器代表客户端浏览器调用API.

来自浏览器的ajax请求将命中MVC控制器,然后进行API调用.然后将结果作为JSON反馈给客户端并在java脚本中处理.

客户端永远不应直接与API通信.

获得认证.

通过成功调用web api令牌端点,我需要找到在MVC应用程序中收到承载令牌后处理承载令牌的最佳方法.

我需要在随后的api调用中使用这个bearer token.

我的计划是把它存放在 System.Web.HttpContext.Current.Session["BearerToken"]

然后我可以创建一个自定义AuthorizationAttribute来检查当前HttpContext中是否存在BearerToken,如果它不存在,客户端将需要重新访问令牌端点.

这看起来可行吗?

我要求各方就此提出意见,因为我不相信这是我项目的最佳解决方案.

Der*_*rek 21

我设法提出了一些我觉得可以很好用的东西.

我正在使用Owin Middleware进行Cookie身份验证.

在MVC应用程序中,我有一个Owin Startup文件,其中配置了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"),

            });
        }
    }
Run Code Online (Sandbox Code Playgroud)

然后我创建了一个AccountController,其中包含两个用于登录和注销的Action方法: -

在登录.

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");
        }
Run Code Online (Sandbox Code Playgroud)

注销

  public ActionResult LogOut()
            {
                Request.GetOwinContext().Authentication.SignOut("ApplicationCookie");

                return RedirectToAction("Login");
            }
Run Code Online (Sandbox Code Playgroud)

保护资源

    [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; }
        }

    }
Run Code Online (Sandbox Code Playgroud)