从MVC获取授权Web API 2

时间:2014-12-27 21:19:15

标签: asp.net-mvc razor asp.net-web-api2 authorize

我在同一个ASP.NET项目中有一个ApiController和一个Controller。我的想法是,我想向第三方公开REST API,并在我公开的REST API之上构建一个网站。

我想从我的MVC控制器(在ProfileController中)中使用REST API(在ProfileApiController中)。两个控制器都需要进行身份验证,ProfileApiController的响应取决于活动的User.Identity。

我怎样才能做到这一点?

以下代码:

namespace Controllers
{
    [Authorize]
    public class ProfileApiController : ApiController
    {

        [Route("api/profile/{param}")]
        [HttpGet]
        public async Task<IHttpActionResult> GetProfile(string param)
        {
            return this.Ok<IEnumerable<TransferObject>>( /* business logic */ );
        }
    }


    [Authorize]
    public class ProfileController : Controller
    {
        public async Task<ActionResult> GetProfile()
        {
            //Pseudocode -- this is what I'm looking for
            var api = (reference_to_profileapicontroller);
            api.Authenticate(User.Identity);
            var m = api.GetProfile("myparameter");
            //End Pseudocode

            return View(m):
        }
    }

}

我已经尝试了两种方法:

  • 通过HttpClient调用WebApi

        HttpClientHandler h = new HttpClientHandler();
        var client = new HttpClient(h);
        var response = client.GetAsync("http://localhost:4827/api/profile/param/").Result;
        var m = await response.Content.ReadAsAsync<List<TransferObject>>();
        return View(m);
    

但是我在这里坚持将身份从Controller传递给ApiController

  • 直接调用Controller

        var pc = DependencyResolver.Current.GetService<ProfileController>();
        var r = await pc.GetTenseProfile("param");
        var rr = await r.ExecuteAsync(System.Threading.CancellationToken.None);
        var m = await rr.Content.ReadAsAsync<List<TransferObject>>();
        return View(m);
    

但由于需要配置pc.Configuration和pc.Request,这会变成一团糟。这不应该这么难吗?

1 个答案:

答案 0 :(得分:2)

我会按此顺序选择3条路线中的一条。

  1. ControllerApiController共有的逻辑移到一个类中,然后在控制器中使用该类。

    [Authorize]
    public class ProfileApiController : ApiController
    {
        [Route("api/profile/{param}")]
        [HttpGet]
        public async Task<IHttpActionResult> GetProfile(string param)
        {
            // have all business logic in this class
            ProfileClass = newClass = new ProfileClass();
            IList<TransferObject> vm = newClass.GetData();  // from bus rules
    
            return this.Ok<IList<TransferObject>>(vm);
        }
    }
    
    [Authorize]
    public class ProfileController : Controller
    {
        public async Task<ActionResult> GetProfile()
        {
            // have all business logic in this class
            ProfileClass = newClass = new ProfileClass();
            IList<TransferObject> vm = newClass.GetData();  // from bus rules
    
            return View(vm):
        }
    }
    
  2. 通过AJAX使用您的API。这是更多的服务器往返,但使用您设计的API。使用视图中的参数对API控制器进行AJAX调用。

    [Authorize]
    public class ProfileController : Controller
    {
        public async Task<ActionResult> GetProfile()
        {
            return View("myparameter"):
        }
    }
    
  3. 使用基于声明的身份验证,其中包含请求中的标头。如果您正在保护您的API,那么您可能已经在这样做了。如上所示使用HttpClient,然后根据MVC中的用户在标头中添加承载令牌。

    HttpClient client = new HttpClient();
    client.DefaultRequestHeaders.Authorization = 
        new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
    

    这也可能有所帮助:http://www.asp.net/web-api/overview/security/individual-accounts-in-web-api

  4. 选项2和3中有很多冗余代码。控制器最好不要理解业务逻辑并让代码消耗掉它。我不认为在每个Action中都要在MVC代码中创建HttpRequests是一个好习惯。当你不得不重构时,这会导致很多令人头痛的问题。