init
This commit is contained in:
36
src/main/resources/application.yml
Normal file
36
src/main/resources/application.yml
Normal file
@@ -0,0 +1,36 @@
|
||||
server:
|
||||
port: 8080
|
||||
|
||||
|
||||
|
||||
|
||||
spring:
|
||||
application:
|
||||
name: authorization-server-standalone
|
||||
data:
|
||||
redis:
|
||||
host: localhost
|
||||
port: 6379
|
||||
password: yyds@8848
|
||||
lettuce:
|
||||
pool:
|
||||
max-active: 8 # 最大连接数
|
||||
max-idle: 4 # 最大空闲连接
|
||||
min-idle: 1 # 最小空闲连接
|
||||
max-wait: 2000ms # 获取连接最大等待时间
|
||||
|
||||
|
||||
arrokoth:
|
||||
authorization:
|
||||
server:
|
||||
consent-page: /oauth2/consent
|
||||
authorization-endpoint: /oauth2/authorize
|
||||
issuer: https://www.arrokoth-info.com
|
||||
security:
|
||||
web:
|
||||
login-page: /login
|
||||
logout-success-url: /login?logout
|
||||
permit-urls:
|
||||
- /home/login
|
||||
|
||||
|
||||
87
src/main/resources/templates/consent.html
Normal file
87
src/main/resources/templates/consent.html
Normal file
@@ -0,0 +1,87 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>授权 |统一身份认证服务平台</title>
|
||||
<!-- Bootstrap CSS -->
|
||||
<link rel="stylesheet" th:href="@{/assets/css/bootstrap.min.css}"
|
||||
integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
|
||||
<!-- Custom Styles -->
|
||||
<link rel="stylesheet" th:href="@{/assets/css/consent.css}" crossorigin="anonymous">
|
||||
<script>
|
||||
function cancelConsent() {
|
||||
document.consent_form.reset();
|
||||
document.consent_form.submit();
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Header Section -->
|
||||
<div class="header">
|
||||
<span>OAuth 授权请求</span>
|
||||
<div class="header__links">
|
||||
<a href="#" class="header__link">seven</a>
|
||||
<span>|</span>
|
||||
<a href="#" class="header__link">换个帐号?</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main Content -->
|
||||
<div class="main-container">
|
||||
<div class="app-info">
|
||||
<!-- <img src="/assets/images/app-icon.png" alt="App Icon" class="app-info__icon">-->
|
||||
<div>
|
||||
<span class="app-info__name" th:text="${clientId}"></span>
|
||||
<p class="app-info__description">此第三方应用请求获得以下权限:</p>
|
||||
</div>
|
||||
</div>
|
||||
<form name="consent_form" method="post" th:action="${requestURI}">
|
||||
<input type="hidden" name="client_id" th:value="${clientId}">
|
||||
<input type="hidden" name="state" th:value="${state}">
|
||||
<input th:if="${userCode}" type="hidden" name="user_code" th:value="${userCode}">
|
||||
<!-- Requested Scopes -->
|
||||
<ul class="permissions-list">
|
||||
<li th:each="scope : ${scopes}" class="permissions-item">
|
||||
<label>
|
||||
<input type="checkbox" class="permissions-item__checkbox" name="scope" th:value="${scope.scope}"
|
||||
th:id="${scope.scope}">
|
||||
<span th:text="${scope.description}"></span>
|
||||
</label>
|
||||
</li>
|
||||
</ul>
|
||||
<!-- Previously Approved Scopes -->
|
||||
<p th:if="${not #lists.isEmpty(previouslyApprovedScopes)}">你已授予以下权限:</p>
|
||||
<ul class="permissions-list">
|
||||
<li th:each="scope : ${previouslyApprovedScopes}" class="permissions-item">
|
||||
<label>
|
||||
<input type="checkbox" name="scope" disabled checked th:id="${scope.scope}">
|
||||
<span th:text="${scope.description}"></span>
|
||||
</label>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="buttons">
|
||||
<button class="button button--primary" type="submit" id="submit-consent">同意授权</button>
|
||||
<button class="button button--secondary" type="button" id="cancel-consent" onclick="cancelConsent();">拒绝
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<p style="margin-top: 2rem;">
|
||||
你可以随时在 <a href="#">帐户设置 > 第三方应用</a> 中取消你的授权。
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Footer Section -->
|
||||
<div class="footer">
|
||||
<div class="footer__links">
|
||||
<div class="footer__link"><a href="#">隐私政策</a></div>
|
||||
<div class="footer__link"><a href="#">服务条款</a></div>
|
||||
<div class="footer__link"><a href="#">联系我们</a></div>
|
||||
</div>
|
||||
<p>© 北京阿罗科斯信息技术有限责任公司 版权所有 | 联系我们 | 帮助中心 |</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
410
src/main/resources/templates/login.html
Normal file
410
src/main/resources/templates/login.html
Normal file
@@ -0,0 +1,410 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>登录 | 统一身份认证服务平台</title>
|
||||
<!-- 引入 Bootstrap 样式 -->
|
||||
<link rel="stylesheet" th:href="@{/assets/css/bootstrap.min.css}"
|
||||
integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
|
||||
|
||||
<!-- 自定义样式 -->
|
||||
<style>
|
||||
/* 全局样式 */
|
||||
body {
|
||||
background: linear-gradient(135deg, #f5f7fa, #c3cfe2);
|
||||
height: 100vh;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-family: Arial, sans-serif;
|
||||
}
|
||||
|
||||
.login-container {
|
||||
width: 100%;
|
||||
max-width: 820px;
|
||||
background: white;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.left-panel {
|
||||
width: 50%;
|
||||
padding: 20px;
|
||||
background: linear-gradient(135deg, #4a5568, #333);
|
||||
color: white;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.right-panel {
|
||||
width: 50%;
|
||||
padding: 30px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@media (max-width: 768px) {
|
||||
.login-container {
|
||||
flex-direction: column;
|
||||
padding: 30px;
|
||||
}
|
||||
|
||||
.left-panel, .right-panel {
|
||||
width: 100%;
|
||||
padding: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Tab 样式 */
|
||||
.login-form {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.login-form a {
|
||||
text-decoration: none;
|
||||
color: #333;
|
||||
font-size: 16px;
|
||||
|
||||
border-bottom: 2px solid transparent;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.login-form a.active {
|
||||
border-bottom: 2px solid #e74c3c;
|
||||
color: #e74c3c;
|
||||
}
|
||||
|
||||
/* Tab 内容样式 */
|
||||
.tab-content {
|
||||
display: none;
|
||||
min-height: 260px;
|
||||
overflow: hidden;
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
|
||||
.tab-content.active {
|
||||
display: block;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* 表单样式 */
|
||||
form {
|
||||
padding: 20px;
|
||||
border-radius: 5px;
|
||||
background: #f9f9f9;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.form-group label {
|
||||
width: 70px; /* 固定宽度,确保所有标签对齐 */
|
||||
text-align: right;
|
||||
margin-right: 10px; /* 距离输入框留出空隙 */
|
||||
color: #333;
|
||||
font-weight: normal;
|
||||
white-space: nowrap; /* 防止换行 */
|
||||
}
|
||||
.form-group input,
|
||||
.form-group select,
|
||||
.form-group .captcha-btn {
|
||||
flex: 1;
|
||||
padding: 10px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 5px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.form-group input{
|
||||
flex: 2;
|
||||
}
|
||||
|
||||
#pass-captcha-input{
|
||||
width: 110px;
|
||||
}
|
||||
|
||||
#captcha-image{
|
||||
margin-left: 2px; /* 验证码图片与输入框之间的间距 */
|
||||
/*width: 70px;*/
|
||||
/*height: 50px;*/
|
||||
vertical-align: middle;
|
||||
cursor:pointer;
|
||||
}
|
||||
|
||||
.submit-btn {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
background: linear-gradient(90deg, #e74c3c, #c0392b);
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
color: white;
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
|
||||
.captcha-btn {
|
||||
display: inline-block;
|
||||
color: #333;
|
||||
background-color: #fff;
|
||||
border: 1px solid #333;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.submit-btn:disabled, .captcha-btn:disabled {
|
||||
background-color: #ccc;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
|
||||
.submit-btn:hover {
|
||||
background: linear-gradient(90deg, #c0392b, #e74c3c);
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
/* 社交登录样式 */
|
||||
.social-login {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.social-login a {
|
||||
font-size: 24px;
|
||||
color: #333;
|
||||
margin: 0 10px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.social-login a:hover {
|
||||
transform: scale(1.2);
|
||||
color: #e74c3c;
|
||||
}
|
||||
|
||||
/* 页脚样式 */
|
||||
footer {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
padding: 10px 0;
|
||||
box-shadow: 0 -2px 5px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
footer p {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
color: #777;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- CSRF Token -->
|
||||
<meta name="_csrf" content="${_csrf.token}"/>
|
||||
<meta name="_csrf_header" content="${_csrf.headerName}"/>
|
||||
|
||||
<div class="login-container">
|
||||
<div class="left-panel">
|
||||
<h3>企业级 统一身份认证服务平台</h3>
|
||||
<p>
|
||||
</p>
|
||||
<p>为企业量身定制的安全保障</p>
|
||||
<p>
|
||||
旨在提供一种简单而强大而灵活的认证解决方案,以保护企业应用的安全性和隐私性。它允许用户通过一组凭据(如用户名和密码、手机号验证码或第三方社交账号)登录到多个应用或服务,而无需对每个应用单独进行注册和身份验证</p>
|
||||
<hr>
|
||||
<p>构建于信任之上,确保数据安全与隐私</p>
|
||||
</div>
|
||||
<div class="right-panel">
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<h3>登录 | 统一身份认证服务平台</h3>
|
||||
<p>高效安全,一站式登录体验</p>
|
||||
</div>
|
||||
<!-- Tab 导航 -->
|
||||
<div class="login-form">
|
||||
<a href="#" class="tab-link active" data-tab="password-tab">密码登录</a>
|
||||
<a href="#" class="tab-link" data-tab="wechat-tab">微信登录</a>
|
||||
<a href="#" class="tab-link" data-tab="password-less-tab">免密登录</a>
|
||||
</div>
|
||||
<div class="tab-content active" id="password-tab">
|
||||
<form method="post" th:action="@{/web/login}">
|
||||
<div class="form-group">
|
||||
<label for="username-input">用户名</label>
|
||||
<input id="username-input" name="username" placeholder="请输入用户名" type="text" value="admin">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password-input">密码</label>
|
||||
<input id="password-input" name="password" placeholder="请输入密码" type="password"
|
||||
value="password">
|
||||
</div>
|
||||
<div class="form-group" style="display: none">
|
||||
<label for="pass-captcha-input">验证码</label>
|
||||
<div>
|
||||
<input id="pass-captcha-input" placeholder="请输入验证码" type="text"/>
|
||||
<!-- 新增:验证码图片展示 -->
|
||||
<img id="captcha-image" alt="验证码"
|
||||
src="" onclick="refreshCaptcha()">
|
||||
</div>
|
||||
</div>
|
||||
<div class="alert alert-danger" role="alert" th:if="${param.error}">用户名或密码输入错误,请重新输入。</div>
|
||||
<button class="submit-btn" id="password-tab-submit">登录</button>
|
||||
</form>
|
||||
</div>
|
||||
<!-- Tab 内容 -->
|
||||
<div class="tab-content" id="wechat-tab">
|
||||
<p>请使用微信扫描二维码登录:</p>
|
||||
<div style="height: 200px;"></div>
|
||||
</div>
|
||||
<div class="tab-content" id="password-less-tab">
|
||||
<form method="post" th:action="@{/oauth2/email/login}" id="loginForm">
|
||||
<!-- <input type="hidden" name="_csrf" th:value="${_csrf.token}"/>-->
|
||||
<div class="form-group">
|
||||
<label for="phone-input">手机号/邮箱</label>
|
||||
<input type="text" id="phone-input" name="email" value="546732225@qq.com"
|
||||
placeholder="请输入手机号/邮箱" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="captcha-input">验证码</label>
|
||||
<input type="text" id="captcha-input" name="code" placeholder="请输入验证码" required>
|
||||
</div>
|
||||
<button type="button" class="captcha-btn" id="sendCaptchaBtn">发送验证码</button>
|
||||
<button type="submit" class="submit-btn" id="submitBtn" disabled>登录</button>
|
||||
</form>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<p>注册登录即表示同意 <a href="#">《认证服务条款》</a> 和 <a href="#">《隐私协议》</a></p>
|
||||
</div>
|
||||
<div class="social-login">
|
||||
<a href="#"><i class="fab fa-weixin"></i></a>
|
||||
<a href="#"><i class="fab fa-qq"></i></a>
|
||||
<a href="#"><i class="fab fa-weibo"></i></a>
|
||||
<a href="#"><i class="fab fa-baidu"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer>
|
||||
<p>© 北京阿罗科斯信息技术有限责任公司 版权所有 | 联系我们 | 帮助中心 |</p>
|
||||
</footer>
|
||||
|
||||
<!-- JavaScript 实现 Tab 切换 -->
|
||||
<script th:inline="javascript">
|
||||
const CONTEXT_PATH = /*[[ @{/} ]]*/ ''; // 动态获取 context-path
|
||||
|
||||
// 页面加载时加载验证码
|
||||
window.onload = function () {
|
||||
// refreshCaptcha();
|
||||
};
|
||||
|
||||
document.querySelectorAll('.tab-link').forEach(link => {
|
||||
link.addEventListener('click', function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
// 移除所有 Tab 的 active 类
|
||||
document.querySelectorAll('.tab-link').forEach(tab => tab.classList.remove('active'));
|
||||
document.querySelectorAll('.tab-content').forEach(content => content.classList.remove('active'));
|
||||
|
||||
// 添加当前 Tab 的 active 类
|
||||
this.classList.add('active');
|
||||
const tabId = this.getAttribute('data-tab');
|
||||
document.getElementById(tabId).classList.add('active');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
const sendCaptchaBtn = document.getElementById('sendCaptchaBtn');
|
||||
const submitBtn = document.getElementById('submitBtn');
|
||||
const emailInput = document.getElementById('phone-input');
|
||||
|
||||
let countdown = 60; // 倒计时时间
|
||||
let timer = null;
|
||||
|
||||
// 获取 CSRF Token
|
||||
const csrfToken = document.querySelector('meta[name="_csrf"]').getAttribute('content');
|
||||
const csrfHeader = document.querySelector('meta[name="_csrf_header"]').getAttribute('content');
|
||||
|
||||
// 点击发送验证码按钮
|
||||
sendCaptchaBtn.addEventListener('click', function () {
|
||||
const email = emailInput.value.trim();
|
||||
if (!email) {
|
||||
alert('请输入有效的手机号/邮箱');
|
||||
return;
|
||||
}
|
||||
|
||||
// 发起 POST 请求
|
||||
fetch(`${CONTEXT_PATH}oauth2/email/generate?email=${encodeURIComponent(email)}`)
|
||||
.then(response => {
|
||||
if (response.ok) {
|
||||
return response.json();
|
||||
} else {
|
||||
throw new Error('验证码发送失败');
|
||||
}
|
||||
})
|
||||
.then(data => {
|
||||
// 启用提交按钮
|
||||
submitBtn.disabled = false;
|
||||
// 禁用发送验证码按钮并开始倒计时
|
||||
sendCaptchaBtn.disabled = true;
|
||||
sendCaptchaBtn.textContent = `重新发送(${countdown})`;
|
||||
|
||||
timer = setInterval(() => {
|
||||
countdown--;
|
||||
sendCaptchaBtn.textContent = `重新发送(${countdown})`;
|
||||
if (countdown <= 0) {
|
||||
clearInterval(timer);
|
||||
sendCaptchaBtn.disabled = false;
|
||||
sendCaptchaBtn.textContent = '发送验证码';
|
||||
countdown = 60; // 重置倒计时
|
||||
}
|
||||
}, 1000);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
alert('验证码发送失败,请稍后再试');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
function refreshCaptcha() {
|
||||
fetch(`${CONTEXT_PATH}oauth/web/captcha`)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success && data.data && data.data.image) {
|
||||
document.getElementById('captcha-image').src = data.data.image;
|
||||
} else {
|
||||
console.error('Failed to retrieve captcha:', data.message || 'Unknown error');
|
||||
}
|
||||
})
|
||||
.catch(error => console.error('Error fetching captcha:', error));
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user