1:单点登录有很多框架,比如OAuth 2.0实现,web-sso等等。我选择了解cas,因为cas在网上资料多一些。
cas分为一个服务端和多个客户端。了解的版本为3.5.2。下载下来是有war包的,后面的版本下载下来没有war包。
1.1:有war包的版本:
因为可能要修改里面的源代码,可以自己新建一个cas-server Dynamic Web Project项目,
把cas-server-core\src\main\java下面的代码复制到项目src下面,
把cas-server-3.5.2\cas-server-webapp\src\main\webapp复制到项目的WebContent下面,
cas-server-webapp\src\main\java的代码也复制到项目src下面,这个可以直接修改源代码,但是改了后想还原却不知道
自己改了哪儿。
1.2:没有war包的版本
没有war包的版本可以从github上面拉下来,
地址:https://github.com/apereo/cas-overlay-template/tree/4.2,是把cas-server-webapp打成了一个包,
如果你想更改哪个文件,直接在项目上建立一个与原项目目录相同的,复制源代码到新建的文件进行修改,这种方式改错了很好
还原重改,而不动源代码。
2:cas版本
cas-server版本:cas-server-3.5.2
cas-client版本:cas-client-core-3.2.1
cas-client不需要下载,在cas-server的war包下面有client包。
3:cas-server配置
cas-servlet.xml修改:
p:followServiceRedirects的值改为true,因为退出登录是进入cas的默认页面,当然也可以修改,但是最方便的还
是使进入自己想要的页面,这个值开启后能在退出地址后拼装返回的地址,比http://localhost:8080/cas/logout?
service=要返回的地址。
deployerConfigContext.xml修改、添加:
<bean class="org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler" p:httpClient-ref="httpClient"/>
cas默认的使用https访问的,可以修改代码取消这种访问方式,而使用http。添加一个p:requireSecure= "false",为true就是使用https,为false就是使用http。
<bean class="org.jasig.cas.authentication.handler.support.SimpleTestUsernamePasswordAuthenticationHandler" />
cas默认登录只要是用户名和密码一样就能登录,我们要改为自己的登录验证方式。注释调上面的代码:换成自己的登录方式:mysql,oracle也行。我们使用的是mysql。
<bean class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler">
<property name="dataSource" ref="dataSource" />
<property name="sql" value="select yhdlmm from USER_INFO where zt = 'QY' and is_del='N'
and lower(yhdlzh) = lower(?)" />
<property name="passwordEncoder" ref="MD5PasswordEncoder"/>
</bean>
这段放到注释的那段代码下面。
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost/test"/>
<property name="username" value=""></property>
<property name="password" value=""></property>
</bean>
上面的代码放到最外层。
<bean id="MD5PasswordEncoder" class="org.jasig.cas.service.MyPasswordEncoder"/>
登录密码加密方式,因为数据库密码肯定是加了密的,有的还是不可逆推的,所以要加密传过去验证,上面的代码加入自己的
MyPasswordEncoder 密码加密bean。
ticketGrantingTicketCookieGenerator.xml添加:
<bean id="ticketGrantingTicketCookieGenerator" class="org.jasig.cas.web.support.CookieRetrievingCookieGenerator"
p:cookieSecure="true"
p:cookieMaxAge="-1"
p:cookieName="CASTGC"
p:cookiePath="/cas" />
p:cookieSecure改为false是不使用https,使用true是使用https。
warnCookieGenerator.xml:
<bean id="warnCookieGenerator" class="org.jasig.cas.web.support.CookieRetrievingCookieGenerator"
p:cookieSecure="true"
p:cookieMaxAge="-1"
p:cookieName="CASPRIVACY"
p:cookiePath="/cas" />
p:cookieSecure改为false是不使用https,使用true是使用https。
4:cas-client配置
cas-client不必到网上下载,在cas-server里面能找到cas-client的jar包,引入到自己需要用到单点登录的项目中,不
项目不需要配置太多的东西,只需要在web.xml中添加cas的filter。
<!-- 用于单点退出,该过滤器用于实现单点登出功能,通知其他应用单点登出 -->
<listener>
<listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
</listener>
<!-- 该过滤器用于实现单点退出功能,可选配置。 -->
<filter>
<filter-name>CAS Single Sign Out Filter</filter-name>
<filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CAS Single Sign Out Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 该过滤器负责用户的认证工作,必须启用它 -->
<filter>
<filter-name>CASFilter</filter-name>
<filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
<init-param>
<param-name>casServerLoginUrl</param-name>
<param-value>http://localhost:8080/cas/login</param-value>
<!--这里的server是服务端的IP -->
</init-param>
<init-param>
<param-name>serverName</param-name>
<param-value>http://localhost:8080</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CASFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 该过滤器负责对Ticket的校验工作,必须启用它 -->
<filter>
<filter-name>CAS Validation Filter</filter-name>
<filter-class>
org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter
</filter-class>
<init-param>
<param-name>casServerUrlPrefix</param-name>
<param-value>http://localhost:8080/cas</param-value>
</init-param>
<init-param>
<param-name>serverName</param-name>
<param-value>http://localhost:8080</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CAS Validation Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
<filter-class>
org.jasig.cas.client.util.HttpServletRequestWrapperFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<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 Assertion Thread Local Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
5:单点登录实现:
配置完成了,接下来就是实现以及各种注意事项。
功能实现:
现有两个客户端,一个cas服务器:
http://www.web.com/client1 客户端1
http://www.web.com/client2 客户端2
http://www.web.com/cas SSO认证中心
1: 登录
cas登录的核心在其票据,TGC、TGT、ST。
TGT:
TGT是CAS为用户签发的登录票据,拥有了TGT,用户就可以证明自己在CAS成功登录过。TGT封装了Cookie值以及此
Cookie值对应的用户信息。用户在CAS认证成功后,生成一个TGT对象,放入自己的缓存(Session);同时,CAS
生成cookie(叫TGC,个人理解,其实就是TGT的SessionId),写入浏览器。TGT对象的ID就是cookie的值,当
HTTP再次请求到来时,如果传过来的有CAS生成的cookie,则CAS以此cookie值(SessionId)为key查询缓存中
有无TGT(Session),如果有的话,则说明用户之前登录过,如果没有,则用户需要重新登录。
TGC:
CAS-Server生成TGT放入自己的Session中,而TGC就是这个Session的唯一标识(SessionId),以Cookie形
式放到浏览器端,是CAS Server用来明确用户身份的凭证。
ST:
ST是CAS为用户签发的访问某一服务票据。用户访问service时,service发现用户没有ST,则要求用户去CAS获取
ST。用户向CAS发出获取ST的请求,如果用户的请求中包含cookie,则CAS会以此cookie值为key查询缓存中有无
TGT,如果存在TGT,则用此TGT签发一个ST,返回给用户。用户凭借ST去访问service,service拿ST去CAS验
证,验证通过后,允许用户访问资源。
为了保证ST的安全性:ST 是基于随机生成的,没有规律性。而且,CAS规定 ST 只能存活一定的时间,然后 CAS
Server 会让它失效。而且,CAS 协议规定ST只能使用一次,无论 Service Ticket 验证是否成功,
CASServer 都会清除服务端缓存中的该 Ticket ,从而可以确保一个 Service Ticket 不被使用两次。
注意事项:
1:登录时跳转的页面
由于是不同的客户端,所以各自的登录页面也是会不相同的,但是cas只提供一个登录页面,虽然这个登录页面
可以修改成自己想要的样式,但是改了也是所有client共同使用,这样肯定不符合现有项目,网上搜索出两种
办法,第一种可以在login地址后加一个参数、用户名和密码,根据参数跳转自己自定义需要的登录页
面,我使用的是3.X版本,没有试过。第二种是
2:不需要进行cas拦截的地址
3:登录后client的session与cas的session以及各自的时间