是否可以使用CAS验证Web API?

时间:2016-01-28 18:40:21

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

=== SETUP ===

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

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

=== GOAL ===

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

=== RESOURCES ===

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

1 个答案:

答案 0 :(得分:3)

我没有使用.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。