【问题标题】:Is it possible to authenticate a web API using CAS?是否可以使用 CAS 对 Web API 进行身份验证?
【发布时间】:2016-01-28 18:40:21
【问题描述】:

=== 设置 ===

ASP.net - Visual Studio - MVC & Web API - 实体框架

目前,应用程序正在调用第三方数据库并显示我通过为这些结果创建带有脚手架的新控制器来选择的那些结果。我尝试添加 [authorize] 过滤器并遵循以下文章,但我的网站不要求您登录 CAS。我希望只允许那些注册用户查看该网站。

=== 目标 ===

似乎您可以使用 CAS 的唯一方法是使用表单,但是我很想知道如果您在尝试访问 Web API 时能够要求身份验证,是否可以进行设置。如果用户访问 URL,他们是否有可能必须登录 CAS 才能查看结果?

=== 资源 ===

https://wiki.jasig.org/display/CASC/.Net+Cas+Client https://wiki.jasig.org/display/CASC/ASP.NET+Forms+Authentication

【问题讨论】:

  • 你好,你能做到吗?

标签: c# asp.net asp.net-mvc


【解决方案1】:

我不使用 .Net CAS 客户端,但我相信有一个专门用于 MVC 的客户端。我将以下代码用于 CAS SSO:

AuthController.cs

public class AuthController : Controller
{
    private readonly string _casHost = System.Configuration.ConfigurationManager.AppSettings["CasHost"];
    private readonly string _casXMLNS = "http://www.yale.edu/tp/cas";

    private readonly IBannerIdentityService _bannerIdentityService;

    public ILogger Logger { get; set; }

    public AuthController(IBannerIdentityService bannerIdentityService)
    {
        _bannerIdentityService = bannerIdentityService;
    }

    //
    // GET: /Auth/
    public ActionResult Index()
    {
        return RedirectToAction("Login");
    }

    //
    // GET: /Auth/Login
    public ActionResult Login(string ticket, string ReturnUrl)
    {
        // Make sure CasHost is specified in web.config
        if (String.IsNullOrEmpty(_casHost))
            Logger.Fatal("Could not find CasHost in web.config. Please specify this value for authentication.");

        string strService = Request.Url.GetLeftPart(UriPartial.Path);

        // First time through there is no ticket=, so redirect to CAS login
        if (String.IsNullOrWhiteSpace(ticket))
        {
            if (!String.IsNullOrWhiteSpace(ReturnUrl))
            {
                Session["ReturnUrl"] = ReturnUrl;
            }

            string strRedirect = _casHost + "login?" + "service=" + strService;

            Logger.Debug("Initializing handshake with CAS");
            Logger.DebugFormat("Redirecting to: {0}", strRedirect);

            return Redirect(strRedirect);
        }

        // Second time (back from CAS) there is a ticket= to validate
        string strValidateUrl = _casHost + "serviceValidate?" + "ticket=" + ticket + "&" + "service=" + strService;

        Logger.DebugFormat("Validating ticket from CAS at: {0}", strValidateUrl);

        XmlReader reader = XmlReader.Create(new WebClient().OpenRead(strValidateUrl));
        XDocument xdoc = XDocument.Load(reader);
        XNamespace xmlns = _casXMLNS;

        Logger.DebugFormat("CAS Response: {0}", xdoc.ToString());
        Logger.Debug("Parsing XML response from CAS");

        var element = (from serviceResponse in xdoc.Elements(xmlns + "serviceResponse")
                        from authenticationSuccess in serviceResponse.Elements(xmlns + "authenticationSuccess")
                        from user in authenticationSuccess.Elements(xmlns + "user")
                        select user).FirstOrDefault();

        string strNetId = String.Empty;

        if (element != null)
            strNetId = element.Value;

        if (!String.IsNullOrEmpty(strNetId))
        {
            Logger.DebugFormat("User '{0}' was validated successfully", strNetId);
            Logger.DebugFormat("Loading user data for '{0}'", strNetId);

            // Get banner data
            var bannerUser = _bannerIdentityService.GetBannerIdentityByNetId(strNetId);

            // Make sure banner user isnt null
            if (bannerUser == null)
                throw new ArgumentOutOfRangeException(String.Format("Could not found any banner records for the Net ID ({0}).", strNetId));

            Logger.DebugFormat("Logging in user '{0}' as a system user.", strNetId);

            Response.Cookies.Add(GetFormsAuthenticationCookie(bannerUser));
        }
        else
        {
            return HttpNotFound();
        }

        if (Session["ReturnUrl"] != null)
        {
            ReturnUrl = Session["ReturnUrl"].ToString();
            Session["ReturnUrl"] = null;
        }

        if (String.IsNullOrEmpty(ReturnUrl) && Request.UrlReferrer != null)
            ReturnUrl = Server.UrlEncode(Request.UrlReferrer.PathAndQuery);

        if (Url.IsLocalUrl(ReturnUrl) && !String.IsNullOrEmpty(ReturnUrl))
        {
            return Redirect(ReturnUrl);
        }
        else
        {
            return RedirectToAction("Index", "Home", new { area = "" });
        }
    }

    private HttpCookie GetFormsAuthenticationCookie(BannerIdentity identity)
    {
        Logger.DebugFormat("Building FormsAuthentication Cookie for user: '{0}'", identity.NetId.Value);

        UserPrincipalPoco pocoModel = new UserPrincipalPoco();
        pocoModel.BannerIdentity = identity;

        JavaScriptSerializer serializer = new JavaScriptSerializer();

        string userData = serializer.Serialize(pocoModel);

        FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(
            1,
            identity.NetId.Value,
            DateTime.Now,
            DateTime.Now.AddMinutes(15),
            false,
            userData);

        string encryptedTicket = FormsAuthentication.Encrypt(authTicket);

        return new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
    }
}

Web.Config 看起来像:

<appSettings>
  <add key="CasHost" value="https://auth.myschool.edu/cas/" />
  <add key="webpages:Version" value="3.0.0.0" />
  <add key="webpages:Enabled" value="false" />
  <add key="ClientValidationEnabled" value="true" />
  <add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>
<system.web>
  <compilation debug="true" targetFramework="4.5" />
  <httpRuntime targetFramework="4.5" />
  <authentication mode="Forms">
    <forms loginUrl="~/Auth/Login" timeout="30" defaultUrl="~/Home/Index" cookieless="UseCookies" slidingExpiration="true" path="/" />
  </authentication>
  <authorization>
    <allow users="*" />
  </authorization>
</system.web>

其中有很多额外的代码,因为我喜欢从数据库中提取用户数据并将其附加到表单身份验证 cookie,但希望您能看到我们如何从 CAS 获取用户名。

这将适用于使用 [Authorize] 属性注释的任何控制器,甚至是 WebAPI。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-04-20
    • 2017-02-20
    • 1970-01-01
    • 1970-01-01
    • 2013-11-16
    • 2017-04-08
    • 2017-07-04
    • 2021-11-14
    相关资源
    最近更新 更多