认证中心登录页面默认如下,对于不同项目使用需求,默认提供了登录页title、logo、左侧显示内容等自定义配置(详见配置文件),对于自定义程度更高的需求,则需要项目自行修改主题,以下介绍如何通过自定义主题来切换登录页面image.png

部署认证中心

通过tomcat部署认证中心后,其目录结构如下
image.png

创建主题的配置文件

假设需要添加的主题名为qianxing,则在上述部署路径 WEB-INF/classes下创建配置文件 qianxing.properties,配置文件名即为主题名
第一行引入的是原cas默认的css样式,保持不变即可

  1. # 原cas默认的css样式,如果更改了,某些页面样式将丢失
  2. cas.standard.css.file=/css/cas.css
  3. # 自己的样式以及js
  4. cas.myself.css=/themes/qianxing/css/cas.css
  5. cas.javascript.file=/themes/qianxing/js/jquery-1.4.2.min.js
  6. # 这里的键值可以随意定义,只要在casLoginView中使用th:text="${#themes.code('cas.body.title')}"指定对应的键即可
  7. cas.page.title=中国电信
  8. 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"
}