迁移 CasSsoService 源码并按 CAS war overlay 形态适配 CI
build / build-push (push) Successful in 4m8s

- 复制 CAS 5.3.16 overlay 源码(src/、pom.xml、etc/cas/config/log4j2.xml、docker/cas.properties)及本地构建辅助(build.cmd/build.sh/maven-settings.xml)
- build.yml:maven 产物由 jar 改为 war(cp cas.war app.jar),CI 内源码构建,摆脱 174MB war blob 入库
- Dockerfile:CAS 专用镜像(自签名 keystore 8443 HTTPS + 内置 cas.properties/log4j2.xml + JAVA_OPTS 注入)
- pom.xml:移除 sonatype/shibboleth 外网仓库,依赖全部经 nexus maven-public 解析
- 前端 front/ 不入库(CasSsoFront 仓库独立发布)
This commit is contained in:
2026-08-31 18:55:29 +08:00
parent 7d8f033f11
commit d6583f49f9
24 changed files with 2623 additions and 55 deletions
@@ -0,0 +1,401 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />
<title>登录</title>
<!-- 覆盖 CAS 原生 casLoginView.html:视觉采用 front/CasSsoFront(完整版企业登录页),
逻辑由 native-login.js 接管(含 check-sso 免密预检 + RSA 登录)。
URL 是 /cas/login,所有资源必须绝对路径(相对路径会解析到 /cas/libs/)。 -->
<script src="/cas/front/libs/jquery.min.js?v=2.1"></script>
<script src="/cas/front/js/jsencrypt.min.js?v=2.1"></script>
<script src="/cas/front/js/conf.js?v=2.3"></script>
<script src="/cas/front/js/bschlogin.js?v=2.1"></script>
<script src="/cas/front/js/native-login.js?v=3.0"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html,
body {
height: 100%;
}
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue",
Arial, "PingFang SC", "Microsoft YaHei", sans-serif;
background: #eef2f7;
color: #1f2d4d;
}
.login-wrap {
display: flex;
min-height: 100vh;
}
/* 左侧品牌区 */
.login-banner {
flex: 0 0 46%;
position: relative;
display: flex;
flex-direction: column;
justify-content: center;
padding: 0 7%;
color: #fff;
overflow: hidden;
background: linear-gradient(155deg, #1e3a8a 0%, #2563eb 52%, #3b82f6 100%);
}
.login-banner::before {
content: "";
position: absolute;
top: -140px;
left: -100px;
width: 360px;
height: 360px;
background: radial-gradient(circle, rgba(255, 255, 255, 0.16), transparent 70%);
}
.login-banner::after {
content: "";
position: absolute;
right: -120px;
bottom: -120px;
width: 380px;
height: 380px;
background: radial-gradient(circle, rgba(255, 255, 255, 0.12), transparent 70%);
}
.banner-inner {
position: relative;
z-index: 1;
max-width: 420px;
}
.brand {
display: flex;
align-items: center;
gap: 12px;
margin-bottom: 52px;
}
.brand-logo {
height: 44px;
width: auto;
filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.25));
}
.brand-name {
font-size: 22px;
font-weight: 700;
letter-spacing: 1px;
}
.banner-title {
font-size: 34px;
font-weight: 700;
line-height: 1.35;
margin-bottom: 16px;
}
.banner-desc {
font-size: 16px;
line-height: 1.7;
opacity: 0.9;
margin-bottom: 38px;
}
.banner-points {
list-style: none;
}
.banner-points li {
position: relative;
padding-left: 22px;
font-size: 15px;
line-height: 2.3;
opacity: 0.92;
}
.banner-points li::before {
content: "";
position: absolute;
left: 0;
top: 16px;
width: 7px;
height: 7px;
border-radius: 50%;
background: rgba(255, 255, 255, 0.85);
}
.banner-footer {
position: absolute;
left: 7%;
right: 7%;
bottom: 26px;
z-index: 1;
font-size: 12px;
opacity: 0.7;
}
/* 右侧登录区 */
.login-main {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
padding: 40px 24px;
}
.login-card {
width: 380px;
max-width: 100%;
background: #fff;
border-radius: 14px;
box-shadow: 0 14px 44px rgba(31, 45, 80, 0.12);
padding: 42px 36px 34px;
}
.login-title {
font-size: 22px;
font-weight: 700;
text-align: center;
margin-bottom: 30px;
}
.form-item {
margin-bottom: 18px;
}
.form-item input {
width: 100%;
padding: 13px 14px;
border: 1px solid #dfe3ea;
border-radius: 8px;
font-size: 14px;
color: #1f2d4d;
background: #fbfcfe;
outline: none;
transition: border-color 0.2s, box-shadow 0.2s, background 0.2s;
}
.form-item input:focus {
border-color: #2563eb;
background: #fff;
box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.12);
}
.captcha-row {
display: flex;
gap: 10px;
align-items: center;
}
.captcha-row input {
flex: 1;
}
.captcha-row img {
height: 46px;
cursor: pointer;
border-radius: 8px;
border: 1px solid #dfe3ea;
}
.btn-submit {
width: 100%;
padding: 13px;
border: none;
border-radius: 8px;
font-size: 16px;
font-weight: 600;
color: #fff;
cursor: pointer;
background: linear-gradient(135deg, #2563eb, #3b82f6);
box-shadow: 0 6px 16px rgba(37, 99, 235, 0.28);
transition: transform 0.1s, box-shadow 0.2s, opacity 0.2s;
}
.btn-submit:hover {
box-shadow: 0 8px 22px rgba(37, 99, 235, 0.38);
}
.btn-submit:active {
transform: translateY(1px);
}
.btn-submit:disabled {
opacity: 0.7;
cursor: not-allowed;
box-shadow: none;
}
.warning {
color: #f56c6c;
font-size: 13px;
margin-top: 14px;
text-align: center;
min-height: 20px;
}
/* 登录成功遮罩 */
.login-success {
position: fixed;
inset: 0;
z-index: 99;
display: none;
align-items: center;
justify-content: center;
flex-direction: column;
background: rgba(255, 255, 255, 0.97);
}
.login-success .check-circle {
width: 84px;
height: 84px;
border-radius: 50%;
background: #e8f5ee;
display: flex;
align-items: center;
justify-content: center;
animation: lc-pop 0.35s ease;
}
.login-success .check-circle svg {
width: 44px;
height: 44px;
}
.check-path {
stroke: #22c55e;
stroke-width: 5;
fill: none;
stroke-linecap: round;
stroke-linejoin: round;
stroke-dasharray: 50;
stroke-dashoffset: 50;
animation: lc-draw 0.4s 0.15s forwards ease;
}
.login-success .success-text {
margin-top: 18px;
font-size: 16px;
font-weight: 600;
color: #22c55e;
}
@keyframes lc-pop {
0% {
transform: scale(0.6);
opacity: 0;
}
100% {
transform: scale(1);
opacity: 1;
}
}
@keyframes lc-draw {
to {
stroke-dashoffset: 0;
}
}
/* 移动端:隐藏品牌区,卡片居中 */
@media (max-width: 860px) {
.login-banner {
display: none;
}
.login-wrap {
background: linear-gradient(155deg, #1e3a8a, #3b82f6);
}
.login-card {
box-shadow: 0 14px 44px rgba(0, 0, 0, 0.18);
}
}
</style>
</head>
<body>
<div class="login-wrap">
<aside class="login-banner">
<div class="banner-inner">
<div class="brand">
<img class="brand-logo" src="/cas/front/image/logo.png" alt="logo" />
<span class="brand-name">云海星通</span>
</div>
<h1 class="banner-title">统一身份认证平台</h1>
<p class="banner-desc">一次登录,畅享所有校园应用<br />安全、便捷的单点登录服务</p>
<ul class="banner-points">
<li>统一账号体系,免去多套密码</li>
<li>单点登录,应用间无缝切换</li>
<li>全程加密传输,保障数据安全</li>
</ul>
</div>
<div class="banner-footer">
©2021 bestsch.com inc All Rights reserved
</div>
</aside>
<main class="login-main">
<div class="login-card">
<h2 class="login-title">账号登录</h2>
<form id="loginForm" onsubmit="return false;">
<div class="form-item">
<input type="text" id="user_input" name="username"
placeholder="用户名/手机号/身份证号" autocomplete="username" />
</div>
<div class="form-item">
<input type="password" id="password_input" name="password"
placeholder="请输入密码" autocomplete="current-password" />
</div>
<input type="hidden" id="loginname_input" name="loginname" />
<input type="hidden" id="pwd_input" name="pwd" />
<input type="hidden" id="captcha_hidden" name="captcha" />
<input type="hidden" id="service_hidden" name="service" />
<div class="form-item" id="captchaPanel" style="display:none">
<div class="captcha-row">
<input type="text" id="captcha_input" placeholder="输入验证码" autocomplete="off" />
<img id="captchaImg" title="点击刷新" />
</div>
</div>
<button class="btn-submit" type="button" id="loginBtn">登录</button>
<div class="warning" id="warningLabel"></div>
</form>
</div>
</main>
</div>
<!-- 登录成功遮罩:由 native-login.js 在登录成功后显示 -->
<div class="login-success" id="loginSuccess">
<div class="check-circle">
<svg viewBox="0 0 54 54" xmlns="http://www.w3.org/2000/svg">
<path class="check-path" d="M15 28 L23 36 L40 18" />
</svg>
</div>
<div class="success-text">登录成功</div>
</div>
<!-- 记住密码最佳努力:真实表单提交到隐藏 iframe(不跳转页面);主流程用 AJAX 拿 data.url 手动跳转,互不干扰 -->
<iframe name="pwdMgrFrame" style="display:none"></iframe>
<form id="pwdMgrForm" method="post" action="/cas/api/login" target="pwdMgrFrame" style="display:none">
<input type="text" name="username" id="pm_user" />
<input type="password" name="password" id="pm_pwd" />
<input type="hidden" name="loginname" id="pm_loginname" />
<input type="hidden" name="pwd" id="pm_pwd_enc" />
<input type="hidden" name="captcha" id="pm_captcha" />
<input type="hidden" name="service" id="pm_service" />
</form>
</body>
</html>