从 Web API 在 MVC 中存储承载令牌的位置 [英] Where to store Bearer Token in MVC from Web API

查看:18
本文介绍了从 Web API 在 MVC 中存储承载令牌的位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

场景

我有一个 ASP.NET Web API,它使用 OAuth 密码流来提供不记名令牌以访问其资源.

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

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

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

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

获得身份验证.

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

我需要在对 api 的任何后续调用中使用此不记名令牌.

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

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

这看起来可行吗?

我正在征求人们对此的意见,因为我不相信这是我项目的最佳解决方案.

解决方案

我想出了一些我认为会很好用的东西.

我正在使用 Owin 中间件进行 Cookie 身份验证.

在 MVC 应用程序中,我有一个 Owin 启动文件,其中配置了 Cookie 身份验证:-

 公共类启动{公共无效配置(IAppBuilder 应用程序){//有关如何配置应用程序的详细信息,请访问 http://go.microsoft.com/fwlink/?LinkID=316888app.UseCookieAuthentication(new CookieAuthenticationOptions(){AuthenticationType = "ApplicationCookie",LoginPath = new PathString("/Account/Login"),});}}

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

登录.

public ActionResult Login(LoginModel model,string returnUrl){var getTokenUrl = string.Format(ApiEndPoints.AuthorisationTokenEndpoint.Post.Token, ConfigurationManager.AppSettings["ApiBaseUri"]);使用 (HttpClient httpClient = new HttpClient()){HttpContent 内容 = 新 FormUrlEncodedContent(new[]{new KeyValuePair("grant_type", "password"),new KeyValuePair("username", model.EmailAddress),new KeyValuePair("password", model.Password)});HttpResponseMessage 结果 = httpClient.PostAsync(getTokenUrl, content).Result;字符串 resultContent = result.Content.ReadAsStringAsync().Result;var token = JsonConvert.DeserializeObject(resultContent);AuthenticationProperties 选项 = 新的 AuthenticationProperties();options.AllowRefresh = true;options.IsPersistent = true;options.ExpiresUtc = DateTime.UtcNow.AddSeconds(int.Parse(token.expires_in));var 声明 = 新 []{新索赔(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("登录");}

保护资源

 [授权]公共类 HomeController : 控制器{私有只读 IUserSession _userSession;公共家庭控制器(IUserSession userSession){_userSession = 用户会话;}//回家公共 ActionResult 索引(){ViewBag.EmailAddress = _userSession.Username;ViewBag.AccessToken = _userSession.BearerToken;返回视图();}}公共接口 IUserSession{字符串 用户名 { 获取;}字符串 BearerToken { 获取;}}公共类 UserSession : IUserSession{公共字符串用户名{得到{返回((ClaimsPrincipal)HttpContext.Current.User).FindFirst(ClaimTypes.Name).价值;}}公共字符串 BearerToken{get { return ((ClaimsPrincipal)HttpContext.Current.User).FindFirst("AcessToken").Value;}}}

Scenario

I have an ASP.NET Web API that uses the OAuth Password Flow to provide Bearer Tokens to gain access to its resources.

I'm now in the process of making an MVC app that will need to use this API.

The plan is to have the MVC controllers make calls to the API on behalf of the client browser.

The ajax requests from the browser will hit the MVC controllers and then the API calls are made. Results are then fed back to the client as JSON and handles in java-script.

The client should never communicate directly with the API.

Getting Authenticated.

I need to find the best way to handle the Bearer Token once it has been received in the MVC app via a successful call to the web api token endpoint.

I need to use this bearer token in any subsequent calls to the api.

My plan is to store it in the System.Web.HttpContext.Current.Session["BearerToken"]

I can then create a custom AuthorizationAttribute that will check to see if a BearerToken is present in the current HttpContext, if it is not present, the client will need to revisit the token endpoint.

Does this seem feasible?

I'm asking for peoples opinion on this as I am not convinced this the best solution for my project.

解决方案

I've managed to come up with something that i think will work quite well.

I'm using the Owin Middleware for Cookie Authentication.

Within the MVC Application i have an Owin Startup file where the Cookie Authentication is configured :-

 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"),

            });
        }
    }

I then made an AccountController with two Action methods for Logging In and Logging out :-

Logging In.

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");
        }

Logging Out

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

                return RedirectToAction("Login");
            }

Protecting the Resources

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

    }

这篇关于从 Web API 在 MVC 中存储承载令牌的位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆