csharp 处理从MVC到IdentityServer的上下文切换

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了csharp 处理从MVC到IdentityServer的上下文切换相关的知识,希望对你有一定的参考价值。

using IdentityModel;
using IdentityServer3.Core.Extensions;
using Microsoft.AspNet.Identity;
using Microsoft.Owin.Infrastructure;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;

namespace Identity.OpenIdServer.Controllers
{
    public class LoginController : Controller
    {
        private static Type AuthorizeFormPostResultType = typeof(IdentityServer3.Core.Constants).Assembly.GetType("IdentityServer3.Core.Results.AuthorizeFormPostResult");
        private static Type AuthorizeRedirectResultType = typeof(IdentityServer3.Core.Constants).Assembly.GetType("IdentityServer3.Core.Results.AuthorizeRedirectResult");
        
        [HttpGet]
        [AllowAnonymous]
        [Route(Startup.RouteRootPath + "/Account/CompleteLoginProcess")]                // Need to be "under" the same root path as IDSrvr
        public async Task<ActionResult> CompleteLoginProcess(string id, bool? cancel)
        {
            var owinContext = this.Request.GetOwinContext();

            if ( cancel.HasValue && cancel.Value)
            {
                return await HandleCancelLoginProcess(owinContext, id);
            }

            return await HandleSignIn(owinContext);
        }

        private async Task<ActionResult> HandleCancelLoginProcess(Microsoft.Owin.IOwinContext owinContext, string id)
        {
            var signInMsg = owinContext.Environment.GetSignInMessage(id);

            var authParams = new Uri(signInMsg.ReturnUrl).Query.Split('&').ToDictionary( item => item.Split('=')[0], item => HttpUtility.UrlDecode( item.Split('=')[1]));

            // clean up cookies
            owinContext.Environment.RemovePartialLoginCookie();

            // TODO: Using internal IDSvr infrastructure to post a form back to the RA.  Replace when capability becomes available
            var response = new IdentityServer3.Core.Models.AuthorizeResponse()
            {
                IsError = true,
                RedirectUri = authParams["redirect_uri"],
                State = authParams[IdentityServer3.Core.Constants.AuthorizeRequest.State],
                Error = IdentityServer3.Core.Constants.AuthorizeErrors.AccessDenied,
                ErrorDescription = "cancelled",
                Request = new IdentityServer3.Core.Validation.ValidatedAuthorizeRequest
                {
                    Options = new IdentityServer3.Core.Configuration.IdentityServerOptions(),
                    ResponseMode = authParams[IdentityServer3.Core.Constants.AuthorizeRequest.ResponseMode]
                }
            };

            if (response.Request.ResponseMode == IdentityServer3.Core.Constants.ResponseModes.FormPost)
                return await GenerateFormPostResult(owinContext, response);

            return await GenerateRedirectResult(owinContext, response);
        }

        private async Task<ActionResult> GenerateFormPostResult(Microsoft.Owin.IOwinContext owinContext, IdentityServer3.Core.Models.AuthorizeResponse response)
        {
            var requestMsg = new System.Net.Http.HttpRequestMessage();
            requestMsg.Properties.Add("MS_OwinEnvironment", owinContext.Environment);

            var authFormPostResult = Activator.CreateInstance(
                AuthorizeFormPostResultType,
                response,
                requestMsg
            );

            var task = authFormPostResult.GetType()
                .GetMethod("ExecuteAsync")
                .Invoke(authFormPostResult, new object[] { System.Threading.CancellationToken.None }) as Task<System.Net.Http.HttpResponseMessage>;

            var httpResponseMessage = (await task.ConfigureAwait(false)) as System.Net.Http.HttpResponseMessage;

            foreach (var header in httpResponseMessage.Content.Headers)
                this.HttpContext.Response.Headers.Add(header.Key, header.Value.FirstOrDefault() ?? "");

            return new FileStreamResult(await httpResponseMessage.Content.ReadAsStreamAsync(), "text/html");
        }

        private async Task<ActionResult> GenerateRedirectResult(Microsoft.Owin.IOwinContext owinContext, IdentityServer3.Core.Models.AuthorizeResponse response)
        {
            var authRedirectResult = Activator.CreateInstance(
                AuthorizeRedirectResultType,
                response,
                response.Request.Options
            );

            var task = authRedirectResult.GetType()
                .GetMethod("ExecuteAsync")
                .Invoke(authRedirectResult, new object[] { System.Threading.CancellationToken.None }) as Task<System.Net.Http.HttpResponseMessage>;

            var httpResponseMessage = (await task.ConfigureAwait(false)) as System.Net.Http.HttpResponseMessage;

            return new RedirectResult(httpResponseMessage.Headers.Location.ToString());
        }

        private async Task<ActionResult> HandleSignIn(Microsoft.Owin.IOwinContext owinContext)
        {
            var ticket = await owinContext.Authentication.AuthenticateAsync(Startup.CookieName);

            if (ticket == null || ticket.Identity == null)
            {
                // TODO Log ?
                return Redirect(await owinContext.Environment.GetPartialLoginRestartUrlAsync());
            }

            await owinContext.Environment.UpdatePartialLoginClaimsAsync(new System.Security.Claims.Claim[]
            {
                // The following claims are required by IDSrvr to resume a login
                new System.Security.Claims.Claim("sub", ticket.Identity.GetUserId()),
                new System.Security.Claims.Claim("name", ticket.Identity.Name),
                new System.Security.Claims.Claim("amr", "password"),            // Authentication mechanism
                new System.Security.Claims.Claim("idp", "idsvr"),
                new System.Security.Claims.Claim("auth_time", DateTimeOffset.UtcNow.ToEpochTime().ToString(), "http://www.w3.org/2001/XMLSchema#integer")
            });

            return Redirect(await owinContext.Environment.GetPartialLoginResumeUrlAsync());
        }
    }
}

以上是关于csharp 处理从MVC到IdentityServer的上下文切换的主要内容,如果未能解决你的问题,请参考以下文章

csharp 如果页面对移动/非移动上下文无效,则MVC4操作过滤器属性将重定向到不同的控制器

csharp AJAX GET MVC

csharp MVC模型上的日期格式

csharp 排序,分页,过滤Paging.mvc

csharp Sql Log 1 Mvc

csharp 单元测试MVC JsonResult对象