旧バージョンCASの実装方針
コア原理(CAS 1.0プロトコル)
- ユーザーが保護対象ページ
/admin/admin.aspxにアクセス web.configの権限設定が匿名ユーザーを遮断し、ログインページCasEnter.aspxへ自動リダイレクトCasEnter.aspxはURLにticketパラメータが存在するか判定
- ticketなし:CASサーバーのログイン先へリダイレクト、自サイトアドレスを
serviceとして渡す - ticket付き:
serviceValidateAPIを呼び出しCASサーバーでチケット検証を実行
- CASから返却されたXMLからログインユーザー名をパース
- 検証成功後
FormsAuthentication.SetAuthCookie()を実行しローカルForms認証チケットを発行、対象ページへ遷移 - 以降の保護ディレクトリアクセスはASP.NET Formsがログイン状態を管理
web.config 設定
<system.web>
<authentication mode="Forms">
<!-- loginUrlはCAS入口中継ページのCasEnter.aspxを指定 -->
<forms loginUrl="CasEnter.aspx"
defaultUrl="admin/admin.aspx"
name=".LoginFormsTicket"
path="/"
timeout="40"
protection="All">
</forms>
</authentication>
<authorization>
<allow users="*"/>
</authorization>
</system.web>
<!-- adminディレクトリを匿名アクセス禁止に制限 -->
<location path="admin">
<system.web>
<authorization>
<deny users="?"/>
</authorization>
</system.web>
</location>Code language: HTML, XML (xml)
新しいCASサーバーは標準でHTTPSを強制します。
casUrlにはhttps://127.0.0.1:8443/cas/を記述してください
<appSettings>
<!-- CAS7向けアドレス、末尾にスラッシュ必須 -->
<add key="casUrl" value="https://127.0.0.1:8443/cas/"/>
</appSettings>Code language: HTML, XML (xml)
CasEnter.aspx ページコード
1. CasEnter.aspx フロント側
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="CasEnter.aspx.cs" Inherits="CasStudy.Web.CasEnter" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>CAS中継ログイン</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Label ID="Label1" runat="server"></asp:Label><br />
<asp:HyperLink ID="HyperLink1" runat="server">再認証</asp:HyperLink>
</div>
</form>
</body>
</html>Code language: HTML, XML (xml)
2. CasEnter.aspx.cs コードビハインド
APIをCAS3.0の p3/serviceValidate に更新
廃止されたWebClientの代わりにHttpClientを使用
自己署名証明書への対応追加(新CASのローカル検証に必須)
CAS応答XMLの名前空間を処理
using System;
using System.Configuration;
using System.Net;
using System.Net.Http;
using System.Xml;
using System.Web.Security;
public partial class CasEnter : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string casHost = ConfigurationManager.AppSettings["casUrl"];
string ticket = Request.QueryString["ticket"];
string service = Request.Url.GetLeftPart(UriPartial.Path);
// チケット無しの場合CASログインページへ遷移
if (string.IsNullOrEmpty(ticket))
{
string redirectUrl = $"{casHost}login?service={Uri.EscapeDataString(service)}";
Response.Redirect(redirectUrl);
return;
}
// チケット検証実行
string username = ValidateTicket(casHost, ticket, service);
if (string.IsNullOrEmpty(username))
{
Label1.Text = "申し訳ありません。CAS認証に失敗しました。再試行してください。";
HyperLink1.NavigateUrl = Request.Url.AbsolutePath;
}
else
{
// Forms認証チケットを書き込みローカルログイン完了
FormsAuthentication.SetAuthCookie(username, false);
// 目的のページへリダイレクト
Response.Redirect(FormsAuthentication.DefaultUrl);
}
}
/// <summary>
/// CAS3.0 p3/serviceValidate によるチケット検証
/// </summary>
private string ValidateTicket(string casHost, string ticket, string service)
{
// 新CASでは p3/serviceValidate(CAS3.0プロトコル)の利用が推奨
string validateUrl = $"{casHost}p3/serviceValidate?ticket={Uri.EscapeDataString(ticket)}&service={Uri.EscapeDataString(service)}";
// ローカルテスト用:信頼されていないSSL証明書を許可(本番環境では削除!)
ServicePointManager.ServerCertificateValidationCallback += (s, cert, chain, err) => true;
using var httpClient = new HttpClient();
string xml = httpClient.GetStringAsync(validateUrl).Result;
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
XmlNamespaceManager nsMgr = new XmlNamespaceManager(doc.NameTable);
// CAS3応答XMLの名前空間
nsMgr.AddNamespace("cas", "http://www.yale.edu/tp/cas");
// ユーザーノードを取得
XmlNode userNode = doc.SelectSingleNode("//cas:authenticationSuccess/cas:user", nsMgr);
return userNode?.InnerText;
}
}Code language: HTML, XML (xml)
CASの実装
Previous: インストール