CAS 单点登陆
一、Tomcat配置SSL
1. 生成 server key
以命令方式换到目录%TOMCAT_HOME%,在command命令行输入如下命令:
keytool -genkey -alias tomcat_key -keyalg RSA -storepass changeit -keystore server.keystore -validity 3600
用户名输入域名,如localhost(开发或测试用)或 hostname.domainname(用户拥有的域名),其它全部以Enter跳过,最后确认,此时会在%TOMCAT_HOME%下生成server.keystore文件。
2. 将证书导入的JDK的证书信任库中
这步对于Tomcat的SSL配置不是必须,但对于CAS SSO是必须的,否则会出现如下错误:
edu.yale.its.tp.cas.client.CASAuthenticationException: Unable to validate ProxyTicketValidate.
导入过程分2步,第一步是导出证书,第二步是导入到证书信任库,命令如下:
keytool -export -trustcacerts -alias tomcat_key -file server.cer -keystore server.keystore -storepass changeit
keytool -import -trustcacerts -alias tomcat_key -file server.cer -keystore D:/”Program Files”/Java/jdk1.8.0_60/jre/lib/security/cacerts -storepass changeit
如果有提示,输入Y就可以了。
其它有用keytool命令(列出信任证书库中所有已有证书,删除库中某个证书):
keytool -list -keystore %JAVA_HOME%/jre/lib/security/cacerts >t.txt
keytool -delete -trustcacerts -alias tomcat_key -keystore %JAVA_HOME%/jre/lib/security/cacerts -storepass changeit
注意:CAS 建议不要使用 IP 地址,而要使用机器名或域名。
3.配置Tomcat
在Tomcat的server.xml配置文件中加入:
二、部署CAS Server到Tomcat
- 到cas官网下载cas-server http://developer.jasig.org/cas/(我下载的是4.0.0)
- 解压压缩文件,在解压后的文件夹内找到/modules/cas-server-webapp-4.0.0.war。将其复制到%Tomcat_Home%\webapps下并改名为cas.war
- 启动Tomcat,并测试 https://localhost:8443/cas 看是否访问正常(默认输入用户名和密码一致就可以)。
注:CAS Server 4.0.0 默认登陆验证方式是 AcceptUsersAuthenticationHandler (老版本好像是SimpleTestUsernamePasswordAuthenticationHandler),默认用户名/密码为 casuser/Mellon(cas/WEB-INF/deployerConfigContext.xml 中找到 id=primaryAuthenticationHandler 的bean查看,里面的map也可以自己增加更多个)。我们通常需要从数据库中取出用户名和密码进行验证,所以我们需要修改 deployerConfigContext.xml,配置我们自己的服务认证方式。
三、配置服务认证
CAS Server 负责完成对用户的认证工作,它会处理登录时的用户凭证 (Credentials) 信息,用户名/密码对是最常见的凭证信息。CAS Server 可能需要到数据库检索一条用户帐号信息,也可能在 XML 文件中检索用户名/密码,还可能通过 LDAP Server 获取等,在这种情况下,CAS 提供了一种灵活但统一的接口和实现分离的方式,实际使用中 CAS 采用哪种方式认证是与 CAS 的基本协议分离开的,用户可以根据认证的接口去定制和扩展。
扩展 AuthenticationHandler
CAS 提供扩展认证的核心是 AuthenticationHandler 接口,该接口定义如清单 1 下:
清单 1. AuthenticationHandler定义
public interface AuthenticationHandler {
/**
* Method to determine if the credentials supplied are valid.
* @param credentials The credentials to validate.
* @return true if valid, return false otherwise.
* @throws AuthenticationException An AuthenticationException can contain
* details about why a particular authentication request failed.
*/
boolean authenticate(Credentials credentials) throws AuthenticationException;
/**
* Method to check if the handler knows how to handle the credentials
* provided. It may be a simple check of the Credentials class or something
* more complicated such as scanning the information contained in the
* Credentials object.
* @param credentials The credentials to check.
* @return true if the handler supports the Credentials, false othewrise.
*/
boolean supports(Credentials credentials);
}
该接口定义了 2 个需要实现的方法,supports ()方法用于检查所给的包含认证信息的Credentials 是否受当前 AuthenticationHandler 支持;而 authenticate() 方法则担当验证认证信息的任务,这也是需要扩展的主要方法,根据情况与存储合法认证信息的介质进行交互,返回 boolean 类型的值,true 表示验证通过,false 表示验证失败。
CAS中还提供了对 AuthenticationHandler 接口的一些抽象实现,比如,可能需要在执行authenticate() 方法前后执行某些其他操作,那么可以让自己的认证类扩展自清单 2 中的抽象类:
清单 2. AbstractPreAndPostProcessingAuthenticationHandler定义
public abstract class AbstractPreAndPostProcessingAuthenticationHandler
implements AuthenticateHandler{
protected Log log = LogFactory.getLog(this.getClass());
protected boolean preAuthenticate(final Credentials credentials) {
return true;
}
protected boolean postAuthenticate(final Credentials credentials,
final boolean authenticated) {
return authenticated;
}
public final boolean authenticate(final Credentials credentials)
throws AuthenticationException {
if (!preAuthenticate(credentials)) {
return false;
}
final boolean authenticated = doAuthentication(credentials);
return postAuthenticate(credentials, authenticated);
}
protected abstract boolean doAuthentication(final Credentials credentials) throws AuthenticationException;
}
AbstractPreAndPostProcessingAuthenticationHandler 类新定义了 preAuthenticate() 方法和 postAuthenticate() 方法,而实际的认证工作交由 doAuthentication() 方法来执行。因此,如果需要在认证前后执行一些额外的操作,可以分别扩展 preAuthenticate()和 ppstAuthenticate() 方法,而 doAuthentication() 取代 authenticate() 成为了子类必须要实现的方法。
由于实际运用中,最常用的是用户名和密码方式的认证,CAS 提供了针对该方式的实现,如清单 3 所示:
清单 3. AbstractUsernamePasswordAuthenticationHandler 定义
public abstract class AbstractUsernamePasswordAuthenticationHandler extends
AbstractPreAndPostProcessingAuthenticationHandler{
...
protected final boolean doAuthentication(final Credentials credentials)
throws AuthenticationException {
return authenticateUsernamePasswordInternal((UsernamePasswordCredentials) credentials);
}
protected abstract boolean authenticateUsernamePasswordInternal(
final UsernamePasswordCredentials credentials) throws AuthenticationException;
protected final PasswordEncoder getPasswordEncoder() {
return this.passwordEncoder;
}
public final void setPasswordEncoder(final PasswordEncoder passwordEncoder) {
this.passwordEncoder = passwordEncoder;
}
...
}
基于用户名密码的认证方式可直接扩展自 AbstractUsernamePasswordAuthenticationHandler,验证用户名密码的具体操作通过实现 authenticateUsernamePasswordInternal() 方法达到,另外,通常情况下密码会是加密过的,setPasswordEncoder() 方法就是用于指定适当的加密器。
从以上清单中可以看到,doAuthentication() 方法的参数是 Credentials 类型,这是包含用户认证信息的一个接口,对于用户名密码类型的认证信息,可以直接使用 UsernamePasswordCredentials,如果需要扩展其他类型的认证信息,需要实现Credentials接口,并且实现相应的 CredentialsToPrincipalResolver 接口,其具体方法可以借鉴 UsernamePasswordCredentials 和 UsernamePasswordCredentialsToPrincipalResolver。
JDBC 认证方法
用户的认证信息通常保存在数据库中,因此本文就选用这种情况来介绍。将前面下载的 cas-server-{version}-release.zip 包解开后,在 modules 目录下可以找到包 cas-server-support-jdbc-{version}.jar,其提供了通过 JDBC 连接数据库进行验证的缺省实现,基于该包的支持,我们只需要做一些配置工作即可实现 JDBC 认证。
JDBC 认证方法支持多种数据库,DB2, Oracle, MySQL, Microsoft SQL Server 等均可,这里以 DB2 作为例子介绍。并且假设DB2数据库名: CASTest,数据库登录用户名: db2user,数据库登录密码: db2password,用户信息表为: userTable,该表包含用户名和密码的两个数据项分别为 userName 和 password。
1. 配置 DataSource
打开文件 cas/WEB-INF/deployerConfigContext.xml,添加一个新的 bean 标签,以mysql为例,内容如清单 4 所示:
<!-- Data source definition -->
<bean id="casDataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="url">
<value>jdbc:mysql://localhost:3306/test</value>
</property>
<property name="username">
<value>sites</value>
</property>
<property name="password">
<value>123456</value>
</property>
</bean>
其中 casDataSource 在后面配置 AuthenticationHandler 会被引用,添加数据库驱动程序、连接地址、数据库登录用户名以及登录密码。
2. 配置 AuthenticationHandler
CAS 4.0.0 提供了 3 个基于 JDBC 的 AuthenticationHandler,分别为 BindModeSearchDatabaseAuthenticationHandler, QueryDatabaseAuthenticationHandler, SearchModeSearchDatabaseAuthenticationHandler。
- BindModeSearchDatabaseAuthenticationHandler 是用所给的用户名和密码去建立数据库连接,根据连接建立是否成功来判断验证成功与否;
- QueryDatabaseAuthenticationHandler 通过配置一个 SQL 语句查出密码,与所给密码匹配;
- SearchModeSearchDatabaseAuthenticationHandler 通过配置存放用户验证信息的表、用户名字段和密码字段,构造查询语句来验证。
使用哪个 AuthenticationHandler,需要在 deployerConfigContext.xml 中设置,默认情况下,CAS 4.0.0 使用 AcceptUsersAuthenticationHandler(上面已经提到,需要在 deployerConfigContext.xml 中查看)。
在 deployerConfigContext.xml 文件中可以找到如下配置:
<bean id="primaryAuthenticationHandler"
class="org.jasig.cas.authentication.AcceptUsersAuthenticationHandler">
<property name="users">
<map>
<entry key="casuser" value="Mellon"/>
</map>
</property>
</bean>
我们可以将其注释掉,换成我们希望的一个 AuthenticationHandler,比如,使用QueryDatabaseAuthenticationHandler 或 SearchModeSearchDatabaseAuthenticationHandler 可以分别选取清单 5 或清单 6 的配置。
清单 5. 使用 QueryDatabaseAuthenticationHandler
<bean id="primaryAuthenticationHandler"
class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler">
<property name="dataSource" ref="casDataSource " />
<property name="sql" value="select password from userTable where lower(userName) = lower(?)" />
<!-- 指定密码加密器(可选) -->
<property name="passwordEncoder" ref="passwordEncoder" />
</bean>
<!-- 密码加密器(可以指定自己实现的加密器) -->
<bean id="passwordEncoder"
class="org.jasig.cas.authentication.handler.DefaultPasswordEncoder" >
<constructor-arg name="encodingAlgorithm" value="MD5"/>
<property name="characterEncoding" value="UTF-8"/>
</bean>
清单 6. 使用 SearchModeSearchDatabaseAuthenticationHandler
<bean id="SearchModeSearchDatabaseAuthenticationHandler"
class="org.jasig.cas.adaptors.jdbc.SearchModeSearchDatabaseAuthenticationHandler"
abstract="false" singleton="true" lazy-init="default"
autowire="default" dependency-check="default">
<property name="tableUsers">
<value>userTable</value>
</property>
<property name="fieldUser">
<value>userName</value>
</property>
<property name="fieldPassword">
<value>password</value>
</property>
<property name="dataSource" ref="casDataSource " />
</bean>
另外,由于存放在数据库中的密码通常是加密过的,所以 AuthenticationHandler 在匹配时需要知道使用的加密方法,在 deployerConfigContext.xml 文件中我们可以为具体的 AuthenticationHandler 类配置一个 property,指定加密器类,比如对于 QueryDatabaseAuthenticationHandler,可以修改如清单7所示:
<bean class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler">
<property name="dataSource" ref=" casDataSource " />
<property name="sql" value="select password from userTable where lower(userName) = lower(?)" />
<property name="passwordEncoder" ref="myPasswordEncoder"/>
</bean>
其中 myPasswordEncoder 是对清单 8 中设置的实际加密器类的引用:
<bean id="passwordEncoder" class="org.jasig.cas.authentication.handler.MyPasswordEncoder"/>
这里 MyPasswordEncoder 是根据实际情况自己定义的加密器,实现 PasswordEncoder 接口及其 encode() 方法。
注意:DataSource 依赖于 commons-collections-3.2.jar、commons-dbcp-1.2.1.jar、commons-pool-1.3.jar、数据库驱动包、cas对jdbc的支持包cas-server-support-jdbc-4.0.0.jar,需要找到这几个jar包放进 %TOMCAT_HOME%/webapps/cas/WEB-INF/lib 目录。
然后便可以启动Tomcat使用数据库中的用户名和密码进行登录测试了。
四、扩展 CAS Server 界面
最直接的方法,下载官方源码,直接修改 ^_^
我想大家很有必要具备“任何开源项目都可以自己动手,使用通过源码构建项目并运行”的能力,万一你需要在源码上加点东西呢。
CAS 4.0 默认的页面存放在 cas/WEB-INF/view/jsp/default 下面,如果是源码项目页面存放在 cas-server-webapp\src\main\webapp\WEB-INF\view\jsp\default\ui 目录中。
我们来看一下 cas\WEB-INF\classes\default_views.properties 文件,如果是源码项目,文件位置为:cas-server-webapp\src\main\resources\default_views.properties
### Login view (/login)
casLoginView.(class)=org.springframework.web.servlet.view.JstlView
casLoginView.url=/WEB-INF/view/jsp/default/ui/casLoginView.jsp
### Display login (warning) messages
casLoginMessageView.(class)=org.springframework.web.servlet.view.JstlView
casLoginMessageView.url=/WEB-INF/view/jsp/default/ui/casLoginMessageView.jsp
### Login confirmation view (logged in, warn=true)
casLoginConfirmView.(class)=org.springframework.web.servlet.view.JstlView
casLoginConfirmView.url=/WEB-INF/view/jsp/default/ui/casConfirmView.jsp
### Logged-in view (logged in, no service provided)
casLoginGenericSuccessView.(class)=org.springframework.web.servlet.view.JstlView
casLoginGenericSuccessView.url=/WEB-INF/view/jsp/default/ui/casGenericSuccess.jsp
### Logout view (/logout)
casLogoutView.(class)=org.springframework.web.servlet.view.JstlView
casLogoutView.url=/WEB-INF/view/jsp/default/ui/casLogoutView.jsp
### CAS error view
viewServiceErrorView.(class)=org.springframework.web.servlet.view.JstlView
viewServiceErrorView.url=/WEB-INF/view/jsp/default/ui/serviceErrorView.jsp
viewServiceSsoErrorView.(class)=org.springframework.web.servlet.view.JstlView
viewServiceSsoErrorView.url=/WEB-INF/view/jsp/default/ui/serviceErrorSsoView.jsp
### CAS statistics view
viewStatisticsView.(class)=org.springframework.web.servlet.view.JstlView
viewStatisticsView.url=/WEB-INF/view/jsp/monitoring/viewStatistics.jsp
### Expired Password Error message
casExpiredPassView.(class)=org.springframework.web.servlet.view.JstlView
casExpiredPassView.url=/WEB-INF/view/jsp/default/ui/casExpiredPassView.jsp
### Locked Account Error message
casAccountLockedView.(class)=org.springframework.web.servlet.view.JstlView
casAccountLockedView.url=/WEB-INF/view/jsp/default/ui/casAccountLockedView.jsp
### Disabled Account Error message
casAccountDisabledView.(class)=org.springframework.web.servlet.view.JstlView
casAccountDisabledView.url=/WEB-INF/view/jsp/default/ui/casAccountDisabledView.jsp
### Must Change Password Error message
casMustChangePassView.(class)=org.springframework.web.servlet.view.JstlView
casMustChangePassView.url=/WEB-INF/view/jsp/default/ui/casMustChangePassView.jsp
### Bad Hours Error message
casBadHoursView.(class)=org.springframework.web.servlet.view.JstlView
casBadHoursView.url=/WEB-INF/view/jsp/default/ui/casBadHoursView.jsp
### Bad Workstation Error message
casBadWorkstationView.(class)=org.springframework.web.servlet.view.JstlView
casBadWorkstationView.url=/WEB-INF/view/jsp/default/ui/casBadWorkstationView.jsp
我们根据文件清单对应的文件修改即可。
如果你想保留这些页面,拷贝一份default 目录,然后修改其中对应的文件后,在这个配置文件中将对应路径修改便可。
除此之外,CAS 4.0 还提供了一些协议登录的方式,也就是在不通过登录页面使用账号密码的方式登录,自动授权登录。
比如我们可以从其他平台直接免登陆进入原来需要SSO登录后才可以看到的系统,或者做个U盾,插入U盾的电脑,可以直接访问系统,无需登录。
官方文档:http://jasig.github.io/cas/4.0.x/protocol/CAS-Protocol.html#cas-protocol
五、部署客户端应用
单点登录的目的是为了让多个相关联的应用使用相同的登录过程,本文在讲解过程中构造 2个简单的应用,分别以 casTest1 和 casTest2 来作为示例,它们均只有一个页面,显示欢迎信息和当前登录用户名。这 2 个应用使用同一套登录信息,并且只有登录过的用户才能访问,通过本文的配置,实现单点登录,即只需登录一次就可以访问这两个应用。
1. 与 CAS Server 建立信任关系
- CAS Server 部署在服务器A
- 客户端应用部署在服务B\C
由于客户端应用与 CAS Server 的通信采用 SSL,因此需要A与B\C的jre之间建立信任关系。
CAS Server 我们在文章的前面已经配置好的 SSL,现在我们只需要在客户端B\C上添加服务器A的证书,操作方法:
网上找一个这个文件下载下来 InstallCert.java
然后在客户端服务器上
编译:javac InstallCert.java
运行:JavaInstallCert serverA:8443 其中8443为SSL端口,serverA为服务器名称或域名
并且在接下来出现的询问中输入 1。这样,就将 A 添加到了 B 的 trust store 中(其他客户端服务器一样操作)。
这里要说一下的是 serverA:8443 这里不要写 {IP地址}:8443,要以域名的方式,如本机 localhost:8443 ,或域名方式 www.baidu.com:443
2. 配置 CAS Filter
在Client工程WEB-INF/lib下添加 cas-client-core-3.3.3.jar 包。
修改web.xml如下:
<!-- ======================== 单点登录/登出 ======================== -->
<!-- 该过滤器用于实现单点登出功能,可选配置。 -->
<!-- 登出地址 https://casserver:8443/cas/logout -->
<filter>
<filter-name>CAS Single Sign Out Filter</filter-name>
<filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
</filter>
<!-- 该过滤器负责用户的认证工作,必须启用它 -->
<filter>
<filter-name>CAS Authentication Filter</filter-name>
<filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
<init-param>
<param-name>casServerLoginUrl</param-name>
<param-value>https://localhost:8443/cas/login</param-value>
</init-param>
<init-param>
<param-name>serverName</param-name>
<param-value>http://localhost:8080</param-value>
</init-param>
</filter>
<!-- 该过滤器负责对Ticket的校验工作,必须启用它 -->
<filter>
<filter-name>CAS Validation Filter</filter-name>
<filter-class>org.jasig.cas.client.validation.Cas10TicketValidationFilter</filter-class>
<init-param>
<param-name>casServerUrlPrefix</param-name>
<param-value>https://localhost:8443/cas</param-value>
</init-param>
<init-param>
<param-name>serverName</param-name>
<param-value>http://localhost:8080</param-value>
</init-param>
<init-param>
<param-name>redirectAfterValidation</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<!-- 该过滤器负责实现HttpServletRequest请求的包装, 比如允许开发者通过HttpServletRequest的getRemoteUser()方法获得SSO登录用户的登录名,可选配置。 -->
<filter>
<filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
<filter-class>org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class>
</filter>
<!-- 该过滤器使得开发者可以通过org.jasig.cas.client.util.AssertionHolder来获取用户的登录名。 比如AssertionHolder.getAssertion().getPrincipal().getName()。 -->
<filter>
<filter-name>CAS Assertion Thread Local Filter</filter-name>
<filter-class>org.jasig.cas.client.util.AssertionThreadLocalFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CAS Single Sign Out Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>CAS Authentication Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>CAS Validation Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>CAS Assertion Thread Local Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
</listener>
<!-- ======================== 单点登录/登出结束 ======================== -->
运行Client工程,首次访问任一页面就会跳转到https://localhost:8443/cas/login进行认证。
把你的退出链接设置为:https://localhost:8443/cas/logout 即可实现单点登出,如果需要在系统退出后返回指定页面,我们可以修改源码在logout后面增加参数来实现。
3. 登录用户名的获取
// 1.
request.getRemoteUser();
// 2.
AssertionHolder.getAssertion().getPrincipal().getName()
六、单点登录测试截图
我创建了2个测试项目,首页访问路径分别为:
http://localhost:8080/cas-client-test1/index.jsp
http://localhost:8080/cas-client-test2/index.jsp
1、访问 http://localhost:8080/cas-client-test1/index.jsp 自动跳转到认证页面。
2、登录成功后,自动转到 http://localhost:8080/cas-client-test1/index.jsp 页面。
3、访问 http://localhost:8080/cas-client-test2/index.jsp 因为已经被认证,所以可以直接打开不用再登录。
4、退出后打开退出页面,实际项目中可以通过 httpclient 请求登出地址来进行登出,然后跳转到登录页面。
CAS 单点登陆的更多相关文章
- CAS单点登陆 SSO
什么是单点登陆 SO是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统.它包括可以将这次主要的登录映射到其他应用中用于同一个用户的登录的机制.它是目前比较流行的企业业务整合的解决方 ...
- CAS单点登陆/oAuth2授权登陆
单点登陆 CAS是一个单点登录框架,即Central Authentication Service(中心认证服务) ,开始是由耶鲁大学的一个组织开发,后来归到apereo去管,github地址:htt ...
- cas单点登陆。就这一篇就够了!!!!!
前言: cas是什么我就不累赘说了.就简单说下大致的流程.首先,cas是一个独立的项目.就是一个war包,部署在tomcat上面启动就ok.然后我们要实现单点登陆,无疑是访问系统1,如果没有登录,就跳 ...
- cas单点登陆系统-casServer搭建
最近工作比较忙,空闲的时间在搞单点登陆系统,自己写了一套SSO在GitHub上,过程走通了.通过这个例子,自己熟悉了流程,而且破天荒的使用了抽象设计模式,并且熟悉了cookies和session的使用 ...
- CAS单点登陆的两个原理图
最近学习CAS单点登录,所以在网上找了两张比较清晰的原理图以供参考: [CAS浏览器请求认证序列图] 其中:* ST:Service Ticket,用于客户端应用持有,每个ST对应一个用户在一个客户 ...
- SuperMap iServer之CAS单点登陆搭建流程
一.安装CAS 1.环境准备 cas-server-3.5.2-release.zip apache-tomcat-7.0.42.zip supermap_iserver_8.1.1a 2.安装CAS ...
- CAS单点登陆,URL多出个参数jsessionid导致登陆失败问题
目录: 1.定位问题 2.问题产生的原因 3.解决问题 一 定位问题 首先,如下图所示:输入到地址栏的地址被302重定向到单点登录地址,地址由Response Headers中的参数Location所 ...
- cas单点登陆系统-建立单点登陆系统的应用
上一篇如果已经操作成功,说明casServer已经实现了,下面就是搭建casClient与casServer联合调试.代码已经上传到github上.你可以下载看看,如果自己在搭建的过程中遇到问题,你也 ...
- CAS单点登录相关配置
一.CAS单点登录服务端的部署 部署 把CAS所对应的war包部署到tomcat中 4.品优购资源V1.3\配套软件\配套软件\CAS\cas.war 配置 更改tomcat的端口号 <Conn ...
随机推荐
- Flunetd 用于统一日志记录层的开源数据收集器
传统的日志查看方式 使用fluentd之后 一.介绍 Fluentd是一个开源的数据收集器,可以统一对数据收集和消费,以便更好地使用和理解数据. 几大特色: 使用JSON统一记录 简单灵活可插拔架构 ...
- helpers.bulk时 action_request_validation_exception 异常
语言Python 在开发时,批量插入ES,出现了action_request_validation_exception异常.我的代码是这样的 action = { } helpers.bulk(es, ...
- 微信小程序实现“鲜肉APP”首页效果
项目地址http://git.oschina.net/djcx/WeiXinXiaoChengXu/tree/master 如果您觉得不错,记得给一个star 由于微信小程序目前是当下趋势,正好昨天弄 ...
- springboot启动时报错No session repository could be auto-configured.....
具体异常提示: Error starting ApplicationContext. To display the auto-configuration report re-run your appl ...
- python函数(6):内置函数和匿名函数
我们学了这么多关于函数的知识基本都是自己定义自己使用,那么我们之前用的一些函数并不是我们自己定义的比如说print(),len(),type()等等,它们是哪来的呢? 一.内置函数 由python内部 ...
- ++i,i++和i += 1的区别
++i,i++和i += 1的区别 单条语句:i++;.++i;和 i += 1;等价. int i = 0; ++i; // 或者i++;或者i += 1; cout << i < ...
- CI框架主题切换的功能
CI框架主题切换的功能 本人接触到这个框架不就,属于菜鸟 , 公司现在用CI框架做项目 ,老大要做一个主题切换的功能,说明功能的要求我的脑子里瞬间有几个想法. 脑子里最简单的就是设置全局变量 如 : ...
- js数组去重方法分析与总结
数组去重经常被人拿来说事,虽然在工作中不常用,但他能够很好的考察js基础知识掌握的深度和广度,下面从js的不同阶段总结一下去重的方法. ES3阶段 该阶段主要通过循环遍历数组从而达到去重的目的 多次循 ...
- 排座椅 2008 NOIP 普及组 第二题
题目描述 上课的时候总会有一些同学和前后左右的人交头接耳,这是令小学班主任十分头疼的一件事情.不过,班主任小雪发现了一些有趣的现象,当同学们的座次确定下来之后,只有有限的D对同学上课时会交头接耳.同学 ...
- .net core 2.0学习笔记(二):Hello World & 进阶
官网已经有一个.net core的入手教程(https://www.microsoft.com/net/core#windowscmd),但这个教程完全没有顾及全宇宙第一IDE的感受.今天就跟大家体验 ...