CAS 5.1.X版本自定義jdbc驗(yàn)證

一晌柬、前言

在不同的項(xiàng)目中质欲,可能由于業(yè)務(wù)需求或者架構(gòu)方式的不同共郭,對(duì)于用戶登錄的驗(yàn)證方式也不同祠丝。CAS為我們提供了很多的認(rèn)證模式,其中最常見(jiàn)的認(rèn)證方式有:

  • JDBC認(rèn)證除嘹,可以通過(guò)配置写半,也可以重寫cas相關(guān)方法進(jìn)行自定義認(rèn)證
  • LDAP認(rèn)證
  • Basic認(rèn)證
  • Shrio認(rèn)證
  • Pac4j認(rèn)證
  • MongoDB認(rèn)證
  • Rest認(rèn)證
  • IP黑白名單
  • 第三方認(rèn)證:微信,QQ尉咕,github等

在筆者最近接手的項(xiàng)目中叠蝇,考慮后期驗(yàn)證方式的變化和程序的擴(kuò)展性,決定重寫CAS的驗(yàn)證方法進(jìn)行自定義驗(yàn)證年缎。另外悔捶,對(duì)于登錄的驗(yàn)證信息,我們除了用戶名和密碼单芜,可能還需要部門信息蜕该,驗(yàn)證碼等等,這也需要重寫cas的方法洲鸠。

二堂淡、實(shí)戰(zhàn)

2.1 pom文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.simon.cas</groupId>
    <artifactId>cas_boot</artifactId>
    <version>2.0.1-SNAPSHOT</version>
    <packaging>war</packaging>

    <name>cas_boot</name>
    <description>cas服務(wù)端</description>

    <properties>
        <cas.version>5.1.5</cas.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <springboot.version>2.0.2.RELEASE</springboot.version>
        <spring-cloud.version>Finchley.SR1</spring-cloud.version>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <!--cas-->
        <dependency>
            <groupId>org.apereo.cas</groupId>
            <artifactId>cas-server-webapp-tomcat</artifactId>
            <version>${cas.version}</version>
            <!--這里必須添加type war-->
            <type>war</type>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.apereo.cas</groupId>
            <artifactId>cas-server-support-configuration</artifactId>
            <version>${cas.version}</version>
        </dependency>
        <!--新增支持服務(wù)注冊(cè)-->
        <dependency>
            <groupId>org.apereo.cas</groupId>
            <artifactId>cas-server-support-eureka-client</artifactId>
            <version>${cas.version}</version>
        </dependency>
        <!--新增支持jdbc驗(yàn)證-->
        <dependency>
            <groupId>org.apereo.cas</groupId>
            <artifactId>cas-server-support-jdbc</artifactId>
            <version>${cas.version}</version>
        </dependency>
        <!-- 若不想找驅(qū)動(dòng)可以直接寫下面的依賴即可,其中包括HSQLDB扒腕、Oracle绢淀、MYSQL、PostgreSQL袜匿、MariaDB更啄、Microsoft SQL Server -->
        <dependency>
            <groupId>org.apereo.cas</groupId>
            <artifactId>cas-server-support-jdbc-drivers</artifactId>
            <version>${cas.version}</version>
        </dependency>
        <!--自定義認(rèn)證,重寫Credential-->
        <dependency>
            <groupId>org.apereo.cas</groupId>
            <artifactId>cas-server-core-webflow</artifactId>
            <version>${cas.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apereo.cas</groupId>
            <artifactId>cas-server-webapp-config</artifactId>
            <version>${cas.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.apereo.cas</groupId>
            <artifactId>cas-server-support-validation</artifactId>
            <version>${cas.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-dbcp2</artifactId>
            <version>2.3.0</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <scope>provided</scope>
            <version>3.1.0</version>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.apereo.cas</groupId>
                <artifactId>cas-server-support-bom</artifactId>
                <version>${cas.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>com.rimerosolutions.maven.plugins</groupId>
                <artifactId>wrapper-maven-plugin</artifactId>
                <version>0.0.4</version>
                <configuration>
                    <verifyDownload>true</verifyDownload>
                    <checksumAlgorithm>MD5</checksumAlgorithm>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>${springboot.version}</version>
                <configuration>
                    <mainClass>org.springframework.boot.loader.WarLauncher</mainClass>
                    <addResources>true</addResources>
                    <executable>false</executable>
                    <layout>WAR</layout>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.1.0</version>
                <configuration>
                    <warName>cas</warName>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                    <recompressZippedFiles>false</recompressZippedFiles>
                    <archive>
                        <compress>false</compress>
                        <manifestFile>${project.build.directory}/war/work/org.apereo.cas/cas-server-webapp-tomcat/META-INF/MANIFEST.MF</manifestFile>
                    </archive>
                    <overlays>
                        <overlay>
                            <groupId>org.apereo.cas</groupId>
                            <artifactId>cas-server-webapp-tomcat</artifactId>
                        </overlay>
                    </overlays>
                    <!-- <dependentWarExcludes> -->
                        <!--&lt;!&ndash;war包下的服務(wù)不進(jìn)行初始化&ndash;&gt;-->
                        <!--**/services/*.json-->
                    <!--</dependentWarExcludes>-->
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.3</version>
            </plugin>
        </plugins>
        <finalName>cas</finalName>
    </build>

    <repositories>
        <repository>
            <id>spring-snapshots</id>
            <name>Spring Snapshots</name>
            <url>https://repo.spring.io/snapshot</url>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
        <repository>
            <id>sonatype-releases</id>
            <name>sonatype-releases</name>
            <url>https://oss.sonatype.org/content/repositories/releases/</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
        <repository>
            <id>sonatype-snapshots</id>
            <name>sonatype-snapshots</name>
            <url>http://oss.sonatype.org/content/repositories/snapshots/</url>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
        <repository>
            <id>shibboleth-releases</id>
            <name>shibboleth-releases</name>
            <url>https://build.shibboleth.net/nexus/content/repositories/releases</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
        <repository>
            <id>jasig-dev-legacy</id>
            <name>jasig-dev-legacy</name>
            <url>http://developer.jasig.org/repo/content/groups/m2-legacy</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
        <repository>
            <id>duo-uniconiam</id>
            <name>duo-uniconiam</name>
            <url>https://dl.bintray.com/uniconiam/maven</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
        <repository>
            <id>jitpack</id>
            <name>jitack</name>
            <url>https://jitpack.io</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>
</project>

2.2 配置文件

服務(wù)的配置文件統(tǒng)一使用Spring Cloud config配置中心進(jìn)行管理居灯。

bootstrap.properties

#日志目錄
logging.file=logs/cas.log
#服務(wù)名
spring.application.name=cas
#從配置中心獲取cas-dev.properties配置
spring.profiles.active=dev
#分支
#spring.cloud.config.label=master

#注冊(cè)中心
eureka.client.serviceUrl.defaultZone=http://localhost:8080/eureka-server/eureka
#通過(guò)服務(wù)名獲取配置中心
#spring.cloud.config.discovery.enabled=true
#spring.cloud.config.discovery.serviceId=config-server
#spring.cloud.config.failFast=true
spring.cloud.config.uri = http://localhost:8080/config-server
#獲取配置失敗快速響應(yīng)
spring.cloud.config.failFast=true

cas-dev.properties

##
# CAS服務(wù)上下文配置
#
#訪問(wèn)路徑
server.context-path=/cas
#訪問(wèn)端口
server.port=8080

#關(guān)閉ssl
server.ssl.enabled=false
#設(shè)定持有SSL certificate的key store的路徑
#server.ssl.key-store=classpath:tomcat.keystore
#設(shè)定訪問(wèn)key store的密碼
#server.ssl.key-store-password=123456
#server.ssl.keyAlias=passport.sso.com
# server.ssl.ciphers=
# server.ssl.client-auth=

# server.ssl.key-alias=
# server.ssl.key-store-provider=
# server.ssl.key-store-type=
# server.ssl.protocol=
# server.ssl.trust-store=
# server.ssl.trust-store-password=
# server.ssl.trust-store-provider=
# server.ssl.trust-store-type=

#解決http下登錄狀態(tài)不互通
cas.tgc.secure=false
cas.warningCookie.secure=false

#允許發(fā)出退出控制退出后轉(zhuǎn)發(fā)url
cas.logout.followServiceRedirects=true


server.max-http-header-size=2097152
server.use-forward-headers=true
server.connection-timeout=20000
server.error.include-stacktrace=NEVER
#設(shè)定http header的最小值祭务,默認(rèn): 0
server.tomcat.max-http-post-size=2097152
#設(shè)定Tomcat的base 目錄内狗,如果沒(méi)有指定則使用臨時(shí)目錄
server.tomcat.basedir=build/tomcat
#是否開(kāi)啟access log,默認(rèn): false
server.tomcat.accesslog.enabled=true
#設(shè)定access logs的格式义锥,默認(rèn): common
server.tomcat.accesslog.pattern=%t %a "%r" %s (%D ms)
#設(shè)定Log 文件的前綴柳沙,默認(rèn): access_log
server.tomcat.accesslog.suffix=.log
#設(shè)定tomcat的最大工作線程數(shù),默認(rèn)為: 0
server.tomcat.max-threads=10
#設(shè)定http header使用的拌倍,用來(lái)覆蓋原來(lái)port的value
server.tomcat.port-header=X-Forwarded-Port
#設(shè)定Header包含的協(xié)議赂鲤,通常是 X-Forwarded-Proto,如果remoteIpHeader有值柱恤,則將設(shè)置為RemoteIpValve.
server.tomcat.protocol-header=X-Forwarded-Proto
#設(shè)定使用SSL的header的值数初,默認(rèn)https.
server.tomcat.protocol-header-https-value=https
#設(shè)定remote IP的header,如果remoteIpHeader有值梗顺,則設(shè)置為RemoteIpValve
server.tomcat.remote-ip-header=X-FORWARDED-FOR
#設(shè)定URI的解碼字符集.
server.tomcat.uri-encoding=UTF-8

spring.http.encoding.charset=UTF-8
spring.http.encoding.enabled=true
spring.http.encoding.force=true
##########################################################JDBC驗(yàn)證##############################################################################
###
## Query Database Authentication 數(shù)據(jù)庫(kù)查詢校驗(yàn)用戶名開(kāi)始
##
##查詢賬號(hào)密碼sql泡孩,必須包含密碼字段,根據(jù)sql給予用戶名進(jìn)行查詢根據(jù)密碼字段進(jìn)行鑒定
#cas.authn.jdbc.query[0].sql=select * from sys_user where username=?
##指定上面的sql查詢字段名(必須)
#cas.authn.jdbc.query[0].fieldPassword=password
##指定過(guò)期字段,1為過(guò)期寺谤,若過(guò)期不可用
#cas.authn.jdbc.query[0].fieldExpired=expired
##為不可用字段仑鸥,1為不可用,需要修改密碼
#cas.authn.jdbc.query[0].fieldDisabled=disabled
##數(shù)據(jù)庫(kù)方言hibernate的知識(shí)
#cas.authn.jdbc.query[0].dialect=org.hibernate.dialect.HSQLDialect
##數(shù)據(jù)庫(kù)驅(qū)動(dòng)
#cas.authn.jdbc.query[0].driverClass=org.hsqldb.jdbcDriver
##數(shù)據(jù)庫(kù)連接
#cas.authn.jdbc.query[0].url=jdbc:hsqldb:mem:cas-hsql-database
##數(shù)據(jù)庫(kù)用戶名
#cas.authn.jdbc.query[0].user=sa
##數(shù)據(jù)庫(kù)密碼
#cas.authn.jdbc.query[0].password=
##默認(rèn)加密策略变屁,通過(guò)encodingAlgorithm來(lái)指定算法眼俊,默認(rèn)NONE不加密
#cas.authn.jdbc.query[0].passwordEncoder.type=DEFAULT
#cas.authn.jdbc.query[0].passwordEncoder.characterEncoding=UTF-8
#cas.authn.jdbc.query[0].passwordEncoder.encodingAlgorithm=MD5
#Query Database Authentication 數(shù)據(jù)庫(kù)查詢校驗(yàn)用戶名結(jié)束

##
#Encode Database Authentication 編碼加密開(kāi)始
#   對(duì)密碼進(jìn)行鹽值處理再加密,增加了反查難度
#
#加密次數(shù)
#cas.authn.jdbc.encode[0].numberOfIterations=2
#該列名的值可替代上面的值粟关,但對(duì)密碼加密時(shí)必須取該值進(jìn)行處理
#cas.authn.jdbc.encode[0].numberOfIterationsFieldName=
# 鹽值固定列
#cas.authn.jdbc.encode[0].saltFieldName=username
#靜態(tài)鹽值
#cas.authn.jdbc.encode[0].staticSalt=.
#cas.authn.jdbc.encode[0].sql=select * from sys_user_encode where username=?
#對(duì)處理鹽值后的算法
#cas.authn.jdbc.encode[0].algorithmName=MD5
#cas.authn.jdbc.encode[0].passwordFieldName=password
#cas.authn.jdbc.encode[0].expiredFieldName=expired
#cas.authn.jdbc.encode[0].disabledFieldName=disabled
#cas.authn.jdbc.encode[0].url=jdbc:hsqldb:mem:cas-hsql-database
#cas.authn.jdbc.encode[0].dialect=org.hibernate.dialect.HSQLDialect
#cas.authn.jdbc.encode[0].user=sa
#cas.authn.jdbc.encode[0].password=
#cas.authn.jdbc.encode[0].driverClass=org.hsqldb.jdbcDriver
#Encode Database Authentication 編碼加密結(jié)束

##########################################################Shrio驗(yàn)證##############################################################################
# Shiro Authentication 開(kāi)始
#允許登錄的用戶疮胖,必須要有以下權(quán)限,否則拒絕誊役,多個(gè)逗號(hào)隔開(kāi)
#cas.authn.shiro.requiredPermissions=staff
#允許登錄的用戶获列,必須要有以下權(quán)限谷市,否則拒絕蛔垢,多個(gè)逗號(hào)隔開(kāi)
#cas.authn.shiro.requiredRoles=admin
#shiro配置文件位置
#cas.authn.shiro.config.location=classpath:shiro.ini
#shiro name 唯一
#cas.authn.shiro.name=cas-shiro
# 與Query Authentication一致的加密策略
#cas.authn.shiro.passwordEncoder.type=DEFAULT
# 使用MD5加密
#cas.authn.shiro.passwordEncoder.encodingAlgorithm=MD5
# Shiro Authentication 結(jié)束

##########################################################REST 認(rèn)證##############################################################################
#REST 認(rèn)證開(kāi)始
#請(qǐng)求遠(yuǎn)程調(diào)用接口
#cas.authn.rest.uri=http://localhost:8101/login
#加密策略
#cas.authn.rest.passwordEncoder.type=DEFAULT
#cas.authn.rest.passwordEncoder.characterEncoding=UTF-8
#加密算法
#cas.authn.rest.passwordEncoder.encodingAlgorithm=MD5
#REST 結(jié)束

#設(shè)置默認(rèn)主題 cas5.1.0-cas5.1.6版本無(wú)法使用默認(rèn)主題,需要覆蓋
#cas.theme.defaultThemeName=100000

##
# CAS Cloud Bus Configuration
#
spring.cloud.bus.enabled=false
# spring.cloud.bus.refresh.enabled=true
# spring.cloud.bus.env.enabled=true
# spring.cloud.bus.destination=CasCloudBus
# spring.cloud.bus.ack.enabled=true

endpoints.enabled=false
endpoints.sensitive=true

endpoints.restart.enabled=false
endpoints.shutdown.enabled=false

management.security.enabled=true
management.security.roles=ACTUATOR,ADMIN
management.security.sessions=if_required
management.context-path=/status
management.add-application-context-header=false

security.basic.authorize-mode=role
security.basic.enabled=false
security.basic.path=/cas/status/**

##
# CAS Web Application Session Configuration
#
server.session.timeout=300
server.session.cookie.http-only=true
server.session.tracking-modes=COOKIE

##
# CAS Thymeleaf View Configuration
#
spring.thymeleaf.encoding=UTF-8
#禁止頁(yè)面緩沖
spring.thymeleaf.cache=false
spring.thymeleaf.mode=HTML
#默認(rèn)是.html
#spring.thymeleaf.suffix=.jsp

##
# CAS Log4j Configuration
#
# logging.config=file:/etc/cas/log4j2.xml
server.context-parameters.isLog4jAutoInitializationDisabled=true

##
# CAS AspectJ Configuration
#
spring.aop.auto=true
spring.aop.proxy-target-class=true

##
# CAS Authentication Credentials
#
#cas.authn.accept.users=casuser::Mellon
#不容許靜態(tài)用戶
staticAuthentication=false

#開(kāi)啟識(shí)別json文件迫悠,默認(rèn)false
cas.serviceRegistry.initFromJson=true

#下面所是數(shù)據(jù)源鹏漆,讓spring boot自動(dòng)配置,默認(rèn)cas屏蔽了spring boot自動(dòng)配置创泄,下面的代碼中我們?cè)趕pring boot掃描的目錄中開(kāi)啟這個(gè)配置
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://192.168.10.58:3306/bdc_job?useUnicode=true&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=Ibase2016
spring.datasource.type=org.apache.commons.dbcp2.BasicDataSource

spring.jpa.database=mysql
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect

#連接池配置
##初始化連接:連接池啟動(dòng)時(shí)創(chuàng)建的初始化連接數(shù)量
spring.datasource.dbcp2.initial-size=5
#最大活動(dòng)連接:連接池在同一時(shí)間能夠分配的最大活動(dòng)連接的數(shù)量, 如果設(shè)置為非正數(shù)則表示不限制
spring.datasource.dbcp2.max-active=1000
#最大空閑連接:連接池中容許保持空閑狀態(tài)的最大連接數(shù)量,超過(guò)的空閑連接將被釋放,如果設(shè)置為負(fù)數(shù)表示不限制
spring.datasource.dbcp2.max-idle=100
#從連接池獲取一個(gè)連接時(shí)艺玲,最大的等待時(shí)間,設(shè)置為-1時(shí),如果沒(méi)有可用連接鞠抑,連接池會(huì)一直無(wú)限期等待饭聚,直到獲取到連接為止。
#如果設(shè)置為N(毫秒)搁拙,則連接池會(huì)等待N毫秒秒梳,等待不到法绵,則拋出異常
spring.datasource.dbcp2.max-wait-millis=60000
#通過(guò)這個(gè)池創(chuàng)建連接的默認(rèn)自動(dòng)提交狀態(tài)。如果不設(shè)置酪碘,則setAutoCommit 方法將不被調(diào)用
spring.datasource.dbcp2.default-auto-commit=true
#通過(guò)這個(gè)池創(chuàng)建連接的默認(rèn)只讀狀態(tài)朋譬。如果不設(shè)置,則setReadOnly  方法將不被調(diào)用兴垦。(部分驅(qū)動(dòng)不支持只讀模式徙赢,如:Informix)
spring.datasource.dbcp2.default-read-only=false
#指明在從池中租借對(duì)象時(shí)是否要進(jìn)行驗(yàn)證有效,如果對(duì)象驗(yàn)證失敗探越,則對(duì)象將從池子釋放狡赐,然后我們將嘗試租借另一個(gè)
spring.datasource.dbcp2.test-on-borrow=true

#自定義屬性 這些屬性我們?cè)趈dbc驗(yàn)證的時(shí)候需要
#用戶名,密碼查詢
user.password.query.sql = select u.USERID,u.DEVICESTRING as DEVICE_,u.UKEYSTRING as UKEY_ from USERINFO u left join ORGANINFO o on u.USERID=o.RID where u.LOGINNAME = ? and u.USERPASSWORD = ?
#ukey查詢
user.ukey.query.sql = select u.USERID from USERINFO u left join ORGANINFO o on u.USERID=o.RID where u.UKEYSTRING = ?
#系統(tǒng)配置查詢(通過(guò)系統(tǒng)配置服務(wù)獲取自定義界面的一些配置信息的sql語(yǔ)句)
syscfg.query.sql = select SVALUE from SYSKEY where CCATALOG = ? and SKEY = ?

2.3 擴(kuò)展登錄信息

cas默認(rèn)提供的登錄信息往往不能滿足我們的需求钦幔,在這里我們將增加系統(tǒng)名阴汇,驗(yàn)證碼作為登錄的擴(kuò)展信息

繼承RememberMeUsernamePasswordCredential擴(kuò)展登錄信息

public class UsernamePasswordSubSystemCredential extends RememberMeUsernamePasswordCredential {

  /**
   * 驗(yàn)證碼
   */
  private String captcha;

  /**
   * 子系統(tǒng)
   */
  private String system;

  /**
   * 獲取驗(yàn)證碼
   *
   * @return
   *        驗(yàn)證碼
   */
  public String getCaptcha() {
    return captcha;
  }

  /**
   * 設(shè)置驗(yàn)證碼
   *
   * @param captcha
   *        驗(yàn)證碼
   */
  public void setCaptcha(String captcha) {
    this.captcha = captcha;
  }

  /**
   * 獲取子系統(tǒng)
   *
   * @return
   *        子系統(tǒng)
   */
  public String getSystem() {
    return system;
  }

  /**
   * 設(shè)置子系統(tǒng)
   *
   * @param system
   *        子系統(tǒng)
   */
  public void setSystem(String system) {
    this.system = system;
  }


  /**
   * 計(jì)算hash碼.
   *
   * 根據(jù)規(guī)范,一旦重寫{@code equals()}就必須重寫此{(lán)@code hashCode()}方法节槐。
   */
  @Override
  public int hashCode() {
    return new HashCodeBuilder().appendSuper(super.hashCode()).append(this.system).append(this.getCaptcha()).toHashCode();
  }
}

將擴(kuò)展的登錄信息綁定到登錄的webflow流程中

public class CustomWebflowConfigurer extends AbstractCasWebflowConfigurer {
  /**
   * 注入系統(tǒng)配置查詢bean
   */
  @Autowired
  private SysConfigQueryService sysConfigQueryService;

  /**
   * 構(gòu)造函數(shù)
   *
   * @param flowBuilderServices
   * @param loginFlowDefinitionRegistry
   */
  public CustomWebflowConfigurer(FlowBuilderServices flowBuilderServices, FlowDefinitionRegistry loginFlowDefinitionRegistry) {
    super(flowBuilderServices, loginFlowDefinitionRegistry);
  }

  @Override
  protected void doInitialize() throws Exception {
    Flow flow = getLoginFlow();
    bindCredential(flow);
  }

  /**
   * 綁定輸入信息
   *
   * @param flow
   *          流程
   */
  protected void bindCredential(Flow flow){
    //重寫綁定自定義credential
    createFlowVariable(flow,CasWebflowConstants.VAR_ID_CREDENTIAL,UsernamePasswordSubSystemCredential.class);
    //登錄頁(yè)綁定新參數(shù)
    final ViewState state = (ViewState)flow.getState(CasWebflowConstants.STATE_ID_VIEW_LOGIN_FORM);

    final BinderConfiguration cfg = getViewStateBinderConfiguration(state);
    //由于用戶名以及密碼已經(jīng)綁定搀庶,所以只需對(duì)新加系統(tǒng)參數(shù)綁定即可
    //參數(shù)1 :字段名
    //參數(shù)2 :轉(zhuǎn)換器
    //參數(shù)3 :是否必須的字段
    cfg.addBinding(new BinderConfiguration.Binding("system", null, false));
    cfg.addBinding(new BinderConfiguration.Binding("captcha",null,false));

    //進(jìn)入viewstate前傳入?yún)?shù)(在系統(tǒng)參數(shù)綁定之后設(shè)置)
    ActionList entryActionList = state.getEntryActionList();
    entryActionList.add(createEvaluateAction("viewScope.newReg="+sysConfigQueryService.getNewRegister()));
    entryActionList.add(createEvaluateAction("viewScope.pwdReset="+sysConfigQueryService.getResetPassword()));
    entryActionList.add(createEvaluateAction("viewScope.codeValidate="+sysConfigQueryService.getImageValidate()));
    //系統(tǒng)名稱
    entryActionList.add(createEvaluateAction("viewScope.sysTitle="+sysConfigQueryService.getSysTitle()));
  }
}

在上面的代碼中,我們除了綁定新添加的登錄信息铜异,還設(shè)置entryActionList(這個(gè)是Spring webflow的一個(gè)自定義切點(diǎn)哥倔,表示進(jìn)入某個(gè) state 之后,做其他事情之前揍庄,執(zhí)行相關(guān)業(yè)務(wù)邏輯咆蒿。Spring Web Flow 共定義了5個(gè)切入點(diǎn),具體可以查看https://docs.spring.io/spring-webflow/docs/2.5.0.RELEASE/reference/html/el.html#el-variable-viewScope )蚂子,這樣在頁(yè)面上可以通過(guò)${newReg},${pwdReset}...獲取傳入的相關(guān)信息來(lái)進(jìn)行有一些邏輯操作沃测。需要注意的是上面代碼綁定新登錄信息和設(shè)置entryActionList的順序不能改變,否則在驗(yàn)證的時(shí)候無(wú)法獲取新增的登錄信息食茎。另外蒂破,SysConfigQueryService的代碼也不貼出來(lái)了,這里主要就是通過(guò)jdbcTemplate查詢系統(tǒng)配置信息别渔。

注冊(cè)修改后的登錄流程

@Configuration("customerAuthWebflowConfiguration")
@EnableConfigurationProperties(value = CasConfigurationProperties.class)
@AutoConfigureBefore(value = CasWebflowContextConfiguration.class)
public class CustomerAuthWebflowConfiguration {

  @Autowired
  @Qualifier("logoutFlowRegistry")
  private FlowDefinitionRegistry logoutFlowRegitry;

  @Autowired
  @Qualifier("loginFlowRegistry")
  private FlowDefinitionRegistry loginFlowRegistry;

  @Autowired
  @Qualifier("builder")
  private FlowBuilderServices builder;

  @Bean
  public CasWebflowConfigurer customWebflowConfigurer() {
    final CustomWebflowConfigurer customWebflowConfigurer = new CustomWebflowConfigurer(builder, loginFlowRegistry);
    customWebflowConfigurer.setLogoutFlowDefinitionRegistry(logoutFlowRegitry);
    return customWebflowConfigurer;
  }
}

2.4 自定義驗(yàn)證

這里我們使用jdbc進(jìn)行驗(yàn)證附迷,通過(guò)用戶登錄信息使用jdbcTemplate進(jìn)行查詢。

繼承AbstractPreAndPostProcessingAuthenticationHandler進(jìn)行自定義認(rèn)證

public class UsernamePasswordSystemAuthenticationHandler extends AbstractPreAndPostProcessingAuthenticationHandler {

  /**
   * 為了符合cacheService key的名稱定義格式哎媚。
   */
  public static final String CSUFFIX_USERLOGIN = "_2ae941e8-21e5-4013-9568-4dcee975333a";

  /**
   * 根據(jù)用戶名和密碼查詢sql語(yǔ)句
   */
  @Value("${user.password.query.sql}")
  private String userQuerySql;

  /**
   * 根據(jù)ukey查詢sql語(yǔ)句
   */
  @Value("${user.ukey.query.sql}")
  private String uKeyQuerySql;

  /**
   * jdbc模板
   */
  @Autowired
  private JdbcTemplate jdbcTemplate;

  /**
   * 構(gòu)造函數(shù)
   *
   * @param name
   * @param servicesManager
   * @param principalFactory
   * @param order
   */
  public UsernamePasswordSystemAuthenticationHandler(String name, ServicesManager servicesManager, PrincipalFactory principalFactory, Integer order) {
    super(name, servicesManager, principalFactory, order);
  }


  @Override
  protected HandlerResult doAuthentication(Credential credential) throws GeneralSecurityException, PreventedException {
    final UsernamePasswordSubSystemCredential upssc = (UsernamePasswordSubSystemCredential) credential;
    final String username = upssc.getUsername();
    //這里我省略了jdbc驗(yàn)證代碼喇伯,大家可以自己去實(shí)現(xiàn)
    if(username.equals("admin")){
      return createHandlerResult(upssc, this.principalFactory.createPrincipal(upssc.getUsername(),Collections.emptyMap()), null);
    }
    return null;
  }

  @Override
  public boolean supports(Credential credential) {
    return credential instanceof UsernamePasswordSubSystemCredential;
  }
}

注冊(cè)自定義驗(yàn)證器

@Import({DataSourceAutoConfiguration.class})
@Configuration("customAuthenticationEventExecutionPlanConfiguration")
@EnableConfigurationProperties(CasConfigurationProperties.class)
public class CustomAuthenticationEventExecutionPlanConfiguration implements AuthenticationEventExecutionPlanConfigurer {
  @Autowired
  @Qualifier("servicesManager")
  private ServicesManager servicesManager;

  @Autowired
  @Qualifier("jdbcPrincipalFactory")
  public PrincipalFactory jdbcPrincipalFactory;


  /**
   * 注冊(cè)驗(yàn)證器
   *
   * @return
   */
  @Bean
  public AuthenticationHandler customAuthenticationHandler() {
    //優(yōu)先驗(yàn)證
    return new UsernamePasswordSystemAuthenticationHandler
            ("customAuthenticationHandler", servicesManager,new DefaultPrincipalFactory(),1);
  }

  //注冊(cè)自定義認(rèn)證器
  @Override
  public void configureAuthenticationExecutionPlan(final AuthenticationEventExecutionPlan plan) {
    plan.registerAuthenticationHandler(customAuthenticationHandler());
  }
}

我們?cè)诖a中增加了@Import({DataSourceAutoConfiguration.class}),開(kāi)啟Spring Boot數(shù)據(jù)源自動(dòng)配置,這樣才可以使用使用jdbcTemplate拨与。為什么在這里配置的稻据,因?yàn)槲視?huì)將個(gè)類配置在Spring Boot的自動(dòng)配置掃描目錄,當(dāng)然你也可以配置在其它地方买喧,保證其被掃描到就可以捻悯。

2.5 其它Bean配置

為了在自定義驗(yàn)證的類中注入其它bean執(zhí)行驗(yàn)證邏輯箩朴,例如:注入緩沖bean,實(shí)現(xiàn)緩沖邏輯秋度;注入系統(tǒng)配置bean,獲取系統(tǒng)配置信息等炸庞,我們需要在這里式配置相關(guān)的bean,使其能被Spring Boot掃描到荚斯。

@Configuration
public class BeansConfiguration {
  @Value("${syscfg.query.sql}")
  private String syscfgQuerySql;

  @Autowired
  private JdbcTemplate jdbcTemplate;

  @Bean
  SysConfigQueryService sysConfigQueryService(){
    return new SysConfigQueryService(syscfgQuerySql,jdbcTemplate);
  }

  @Bean
  ICacheService cacheService(){
    return new CacheService();
  }

2.6 配置spring.factories

SpringFactoriesLoader屬于Spring框架私有的一種擴(kuò)展方案,其主要功能就是從指定的配置文件META-INF/spring.factories加載配置埠居。通過(guò)這個(gè)方法,我們就能將自定義的認(rèn)證方法讓spring boot 自動(dòng)配置掃描到事期。

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.simo.cas.config.CustomerAuthWebflowConfiguration,com.simon.cas.config.CustomAuthenticationEventExecutionPlanConfiguration,com.simon.cas.config.BeansConfiguration

三滥壕、登錄頁(yè)面

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1"/>
    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
    <title th:text="${sysTitle}">這里使用了傳遞進(jìn)來(lái)的屬性</title>
    <link rel="stylesheet" th:href="@{/themes/hzww/css/hzww.css}"/>
    <script th:src="@{/themes/common/js/sha1.min.js}"></script>
    <script th:src="@{/themes/common/js/jquery-1.x.min.js}"></script>
    <script th:src="@{/themes/common/js/login.min.js}"></script>
    <script th:src="@{/themes/common/js/jquery.cookie.min.js}"></script>
</head>
<body>
<div id="content">
    <img class="bgimg" alt="" th:src="@{/themes/hzww/images/ibase_loginBg_01.jpg}"/>
    <div class="header">
        <div class="header_left">
            <img th:src="@{/themes/hzww/images/Login_logo.png}">

            <p th:text="${sysTitle}">這里使用了傳遞進(jìn)來(lái)的屬性</p>
        </div>
    </div>
    <div class="login_center">
        <div class=login-title>
            <h2>歡迎登錄</h2>
            <span>Welcome To Login</span>
        </div>
        <div class="login-box">
            <form id="login_form" method="post" th:object="${credential}">
                <div class="form_radio">
                    <div th:if="${#fields.hasErrors('*')}" class="errDiv">
                        <span th:each="err : ${#fields.errors('*')}" th:utext="${err}"/>
                    </div>
                </div>
                <div class="login_txtBorder" th:unless="${openIdLocalId}">
                    <input type = "text" id="login_user" name="username" th:disabled="${guaEnabled}" th:field="*{username}"  placeholder='登錄賬戶'/>
                </div>
                <div class="login_txtBorder">
                    <input type="password" id="login_pw"  name="password" th:field="*{password}"  placeholder='請(qǐng)輸入密碼'>
                </div>
                <div class="login_captchaBorder>
                    <input type="text" id="login_captcha"  name="captcha" th:field="*{captcha}" placeholder='請(qǐng)輸入右方驗(yàn)證碼' autocomplete="off">
                    <div class="login_captcha_img"><img id="cimg" src="" onclick="" title="看不清?點(diǎn)擊更換另一個(gè)兽泣。"/></div>
                </div>


                <input type="hidden" name="execution" th:value="${flowExecutionKey}"/>
                <input type="hidden" name="_eventId" value="submit"/>
                <input type="hidden" name="geolocation"/>
                <input type="hidden" id="system" name="system" th:field="*{system}">
                <input id="login_submit" type="submit" class="normal_input" th:value="#{screen.welcome.button.login}" value="登錄">
            </form>
        </div>
    </div>
</div>
</body>

<script type="text/javascript" th:inline="javascript">

</script>
</html>

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末绎橘,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子唠倦,更是在濱河造成了極大的恐慌称鳞,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,265評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件稠鼻,死亡現(xiàn)場(chǎng)離奇詭異冈止,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)候齿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門熙暴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人慌盯,你說(shuō)我怎么就攤上這事周霉。” “怎么了亚皂?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,852評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵俱箱,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我孕讳,道長(zhǎng)匠楚,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,408評(píng)論 1 283
  • 正文 為了忘掉前任厂财,我火速辦了婚禮,結(jié)果婚禮上峡懈,老公的妹妹穿的比我還像新娘璃饱。我一直安慰自己,他們只是感情好肪康,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布荚恶。 她就那樣靜靜地躺著撩穿,像睡著了一般。 火紅的嫁衣襯著肌膚如雪谒撼。 梳的紋絲不亂的頭發(fā)上食寡,一...
    開(kāi)封第一講書(shū)人閱讀 49,772評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音廓潜,去河邊找鬼抵皱。 笑死,一個(gè)胖子當(dāng)著我的面吹牛辩蛋,可吹牛的內(nèi)容都是我干的呻畸。 我是一名探鬼主播,決...
    沈念sama閱讀 38,921評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼悼院,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼伤为!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起据途,我...
    開(kāi)封第一講書(shū)人閱讀 37,688評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤绞愚,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后颖医,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體爽醋,經(jīng)...
    沈念sama閱讀 44,130評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評(píng)論 2 325
  • 正文 我和宋清朗相戀三年便脊,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蚂四。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,617評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡哪痰,死狀恐怖遂赠,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情晌杰,我是刑警寧澤跷睦,帶...
    沈念sama閱讀 34,276評(píng)論 4 329
  • 正文 年R本政府宣布,位于F島的核電站肋演,受9級(jí)特大地震影響抑诸,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜爹殊,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評(píng)論 3 312
  • 文/蒙蒙 一蜕乡、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧梗夸,春花似錦层玲、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,740評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)畔派。三九已至,卻和暖如春润绵,著一層夾襖步出監(jiān)牢的瞬間线椰,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,967評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工尘盼, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留憨愉,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,315評(píng)論 2 360
  • 正文 我出身青樓悔叽,卻偏偏與公主長(zhǎng)得像莱衩,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子娇澎,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理笨蚁,服務(wù)發(fā)現(xiàn),斷路器趟庄,智...
    卡卡羅2017閱讀 134,629評(píng)論 18 139
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,773評(píng)論 6 342
  • Spring Web MVC Spring Web MVC 是包含在 Spring 框架中的 Web 框架括细,建立于...
    Hsinwong閱讀 22,353評(píng)論 1 92
  • 1.1 spring IoC容器和beans的簡(jiǎn)介 Spring 框架的最核心基礎(chǔ)的功能是IoC(控制反轉(zhuǎn))容器,...
    simoscode閱讀 6,702評(píng)論 2 22
  • 本集匿名投票榮譽(yù)榜 詩(shī)魁:樂(lè)天居士戚啥,作品《11 七絕·隨園感懷》 副魁:繁花落盡深眸奋单,作品《16 七絕 山居(新...
    霙愔閱讀 594評(píng)論 0 0