认证中心登录页面默认如下,对于不同项目使用需求,默认提供了登录页title、logo、左侧显示内容等自定义配置(详见配置文件),对于自定义程度更高的需求,则需要项目自行修改主题,以下介绍如何通过自定义主题来切换登录页面
部署认证中心
创建主题的配置文件
假设需要添加的主题名为qianxing,则在上述部署路径 WEB-INF/classes下创建配置文件 qianxing.properties,配置文件名即为主题名
第一行引入的是原cas默认的css样式,保持不变即可
# 原cas默认的css样式,如果更改了,某些页面样式将丢失
cas.standard.css.file=/css/cas.css
# 自己的样式以及js
cas.myself.css=/themes/qianxing/css/cas.css
cas.javascript.file=/themes/qianxing/js/jquery-1.4.2.min.js
# 这里的键值可以随意定义,只要在casLoginView中使用th:text="${#themes.code('cas.body.title')}"指定对应的键即可
cas.page.title=中国电信
cas.body.title=中国电信统一登录认证
创建css样式文件以及js文件
上述配置文件中我们指定了自定义主题的样式文件路径为 /themes/qianxing/css/cas.css,所以接下来需要在WEB-INF/classes/static/themes 下创建 /qianxing/css 文件夹,并创建 cas.css 文件,这里用来存放样式代码,后续自定义主题登录页的样式代码可以放到该文件中,js文件同理,可创建 /qianxing/js 文件夹来放置js文件
cas.css 示例:
h2 {
color: red;
}
配置自定义登录页面
在 WEB-INF/classes/templates/qianxing 文件夹下创建 casLoginView.html 文件
按照需求编辑出登录页面即可,其中登录表单遵循一定的thymeleaf标准
登录表单参考如下,主要为三个部分:用户名输入框、密码输入框和登录按钮,如果需要修改其样式,添加style或者修改其input标签的class即可
除登录表单外,其他页面布局均可自行定义
<form method="post" th:object="${credential}">
<!-- 用户名输入框,可通过修改class或style来修改样式 -->
<section class="row">
<label for="username" th:utext="#{screen.welcome.label.netid}" />
<div th:unless="${openIdLocalId}">
<input class="required" id="username" size="25" tabindex="1" type="text"
th:disabled="${guaEnabled}"
th:field="*{username}"
th:accesskey="#{screen.welcome.label.netid.accesskey}"
autocomplete="off"
th:value="admin" />
</div>
</section>
<!-- 密码输入框,可通过修改class或style来修改样式 -->
<section class="row">
<label for="password" th:utext="#{screen.welcome.label.password}"/>
<div>
<input class="required" type="password" id="password" size="25" tabindex="2"
th:accesskey="#{screen.welcome.label.password.accesskey}"
th:field="*{password}"
autocomplete="off"
th:value="123456" />
</div>
</section>
<!-- 提交按钮,可通过修改class或style来修改样式 -->
<section>
<input type="hidden" name="execution" th:value="${flowExecutionKey}" />
<input type="hidden" name="_eventId" value="submit" />
<input type="hidden" name="geolocation" />
<input class="btn btn-submit btn-block" name="submit" accesskey="l" th:value="#{screen.welcome.button.login}" tabindex="6" type="submit" />
</form>
完整的 casLoginView.html 案例参考如下
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title th:text="${#themes.code('cas.page.title')}"></title>
<!-- 这里引入了qianxing.properties 中定义的css文件 -->
<link rel="stylesheet" th:href="@{${#themes.code('cas.myself.css')}}"/>
<!-- 这里引入了qianxing.properties 中定义的js文件 -->
<script th:src="@{${#themes.code('cas.javascript.file')}}"></script>
</head>
<body>
<!-- 示例:这里加了个h2标签,其值来源于qianxing.properties 中定义的cas.page.title键值,可任意指定 -->
<h2 th:text="${#themes.code('cas.page.title')}"></h2>
<div>
<form method="post" th:object="${credential}">
<div th:if="${#fields.hasErrors('*')}">
<span th:each="err : ${#fields.errors('*')}" th:utext="${err}" style="color: red" />
</div>
<h4 th:utext="#{screen.welcome.instructions}"></h4>
<section class="row">
<label for="username" th:utext="#{screen.welcome.label.netid}" />
<div th:unless="${openIdLocalId}">
<input class="required" id="username" size="25" tabindex="1" type="text"
th:disabled="${guaEnabled}"
th:field="*{username}"
th:accesskey="#{screen.welcome.label.netid.accesskey}"
autocomplete="off"
th:value="admin" />
</div>
</section>
<section class="row">
<label for="password" th:utext="#{screen.welcome.label.password}"/>
<div>
<input class="required" type="password" id="password" size="25" tabindex="2"
th:accesskey="#{screen.welcome.label.password.accesskey}"
th:field="*{password}"
autocomplete="off"
th:value="123456" />
</div>
</section>
<section>
<input type="hidden" name="execution" th:value="${flowExecutionKey}" />
<input type="hidden" name="_eventId" value="submit" />
<input type="hidden" name="geolocation" />
<input class="btn btn-submit btn-block" name="submit" accesskey="l" th:value="#{screen.welcome.button.login}" tabindex="6" type="submit" />
</section>
</form>
</div>
</body>
</html>
主题切换
设置默认主题
在配置文件 application-xxx.yml 中加入以下配置指定默认主题,配置文件
# 默认主题
cas:
theme:
defaultThemeName: qianxing
注册时配置主题
注册服务时,指定theme参数即可配置该服务登录时使用的主题,不指定theme参数则会使用默认主题
{
"@class" : "org.apereo.cas.services.RegexRegisteredService",
"serviceId" : "^http://www.baidu.com.*",
"name" : "测试客户端app1",
"id" : 1003,
"description" : "这是app1的客户端",
"evaluationOrder" : 10,
"theme" : "qianxing"
}
Groovy脚本获取主题
创建 Groovy 脚本,方法名称必须为 run ,返回值即为主题名,并且 cas 提供了以下参数
def String run(final Object... args) {
// 请求的服务
def service = args[0]
// 表示注册表中匹配的注册服务的对象。
def registeredService = args[1]
// 查询的字符串
def queryStrings = args[2]
// 请求头
def headers = args[3]
def logger = args[4]
// 返回主题,null表示使用默认主题
// return null
return qianxing
}
注册服务时在theme属性中指定 Groovy 脚本文件位置
{
"@class" : "org.apereo.cas.services.RegexRegisteredService",
"serviceId" : "^http://www.baidu.com.*",
"name" : "测试客户端app1",
"id" : 1003,
"description" : "这是app1的客户端",
"evaluationOrder" : 10,
"theme" : "file:\D:\cas\config\themes.groovy"
}
http请求获取主题
创建一个RestFul接口用于返回主题,cas在接收到响应状态为200的响应时,会将响应body作为主题值
@RestController
@RequestMapping("/test")
public class ThemeController {
@GetMapping("/theme")
public String getTheme(HttpServletRequest request){
// 请求的服务
System.out.println(request.getParameter("service"));
// 返回主题,返回null表示使用默认主题
return "qianxing";
}
}
注册服务时在theme属性中指定 http 接口
{
"@class" : "org.apereo.cas.services.RegexRegisteredService",
"serviceId" : "^http://www.baidu.com.*",
"name" : "测试客户端app1",
"id" : 1003,
"description" : "这是app1的客户端",
"evaluationOrder" : 10,
"theme" : "http://192.168.212.32:8081/demo/test/theme"
}