sso: 分为server client
server即服务端,一个,功能:系统下各个应用的认证都在这里进行
client即客户端,应用,n个。
对于我们这个系统来说
客户端为 zjcms
服务端为 cas_server
我们用2个tomcat分别跑这两个应用,登录cms时,跳转到cas_server登录,服务端认证,认证通过,返回到客户端,并携带我们所需要的信息.
配置客户端:我们使用cas-client 版本为3.2.1
配置服务端:我们使用cas-server 版本为4.0.0
对于客户端配置:
在web.xml中
<!--cas client -->
<listener>
<listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
</listener>
<!--这个filter作用于注销登录 -->
<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>/admin/*</url-pattern>
</filter-mapping>
<!-- 登录认证,未登录用户导向CAS Server进行认证 -->
<filter>
<filter-name>CAS Filter</filter-name>
<filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
<init-param>
<param-name>casServerLoginUrl</param-name>
<param-value>http://localhost:9080/login</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 Filter</filter-name>
<url-pattern>/admin/*</url-pattern>
<url-pattern>/ShowReport.wx</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>
<!-- 存放Assertion到ThreadLocal中 -->
<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>
<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:9080</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>
对于客户端来说:cas 认证成功默认是返回userName,存储在request的principal中,
认证成功还会返回一个ticket存储在session中,我们注销登录就是通过清除session中的令牌实现.
我们通过
AttributePrincipal principal = (AttributePrincipal) getRequest().getUserPrincipal();
获取返回的信息(后面会讲到如何设置我们需要返回的信息)
对于服务端的配置:主要是在WEB-INF 下的deployerConfigContext.xml中
cas默认的一个bean配置为
<bean id="primaryAuthenticationHandler"
class="org.jasig.cas.authentication.AcceptUsersAuthenticationHandler">
<property name="users">
<map>
<entry key="admin" value="admin"/>
</map>
</property>
</bean>
这是未配置数据源
项目中,实现我们自己的数据源,则需要如下配置
<bean id="primaryAuthenticationHandler" class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler">
<property name="dataSource" ref="dataSource"></property>
<property name="sql" value="select PASSWORD from T_USER where NAME=?"></property>
<property name="passwordEncoder" ref="BASE64Encoder"></property>
</bean>
在这个bean中2个功能:一个配置数据源,增加一个bean
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName"><value>${jdbc.Driver}</value></property>
<property name="url"><value>${jdbc.url}</value></property>
<property name="username"><value>${jdbc.name}</value></property>
<property name="password"><value>${jdbc.pwd}</value></property>
</bean>
另一个是配置我们自己的加密法则,
我们cms使用的是自定义的base64加密
添加一个bean
<bean id="BASE64Encoder" class="cn.zfgc.passwordEncoder.DefaultEncoder">
<constructor-arg index="0">
<value>BASE64</value>
</constructor-arg>
</bean>
在java中新建一个DefaultEncoder 实现PasswordEncoder接口
这种加密不算很好,要严谨一点我们需要使用加盐算法
public class DefaultEncoder implements PasswordEncoder {
public DefaultEncoder(String s) {
}
@Override
public String encode(String password) {
return base64Encode(password);
}
/**
* 加密
*/
private String base64Encode(String str){
byte[] b = null;
String result = null;
try {
b = str.getBytes("utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
if (b != null) {
result = new BASE64Encoder().encode(b);
}
return result;
}
}
这样基本的配置已经完成,但是cas默认是要使用https.所以我们需要将https设置为http
第一步:
webapps\cas\WEB-INF\spring-configuration\warnCookieGenerator.xml
<bean id="warnCookieGenerator 这个bean中 将p:cookieSecure="true" 为 p:cookieSecure="false"
第二步:
webapps\cas\WEB-INF\spring-configuration\ticketGrantingTicketCookieGenerator.xml
中<bean id="ticketGrantingTicketCookieGenerator" 将 p:cookieSecure="true" 为 p:cookieSecure="false"
第三步:
webapps\cas\WEB-INF\deployerConfigContext.xml中
<bean id="proxyAuthenticationHandler" 末尾增加 p:requireSecure="false"
第四步:
webapps\cas\WEB-INF\deployerConfigContext.xml中
找到<bean class="org.jasig.cas.services.RegexRegisteredService">这个bean
默认配置为:
<bean class="org.jasig.cas.services.RegexRegisteredService"-->
<!--p:id="0" p:name="HTTP and IMAP" p:description="Allows HTTP(S) and IMAP(S) protocols"-->
<!--p:serviceId="^(https?|imaps?)://.*" p:evaluationOrder="10000001" />
</bean>
更改为
<bean class="org.jasig.cas.services.RegexRegisteredService">
<property name="id" value="1" />
<property name="name" value="HTTP and IMAP on example.com" />
<property name="description" value="Allows HTTP(S) and IMAP(S) protocols" />
<property name="serviceId" value="^(http?|imaps?)://.*" />
<property name="evaluationOrder" value="10000001" />
<property name="allowedAttributes">
<list>
<value>NAME</value>
<value>ROLE_ID</value>
</list>
</property>
</bean>
这样就ok了
配置服务端自定义返回数据:
第一步:
默认配置为
<bean id="attributeRepository" class="org.jasig.services.persondir.support.StubPersonAttributeDao"
p:backingMap-ref="attrRepoBackingMap" >
</bean>
<util:map id="attrRepoBackingMap">
<entry key="uid" value="uid" />
<entry key="eduPersonAffiliation" value="eduPersonAffiliation" />
<entry key="groupMembership" value="groupMembership" />
</util:map>
修改为
<bean id="attributeRepository" class="org.jasig.services.persondir.support.jdbc.SingleRowJdbcPersonAttributeDao">
<constructor-arg index="0" ref="dataSource"></constructor-arg>
<constructor-arg index="1" value="select * from T_USER where {0}"></constructor-arg>
<property name="queryAttributeMapping">
<map>
<entry key="username" value="NAME"></entry>
</map>
</property>
<property name="resultAttributeMapping">
<map>
<entry key="NAME" value="NAME"/>
<entry key="ROLE_ID" value="ROLE_ID"/>
</map>
</property>
</bean>
在我们项目中 需要返回一个ROLE_ID,那么
我们在resultAttributeMapping中多配置一个
<entry key="ROLE_ID" value="ROLE_ID"/> value对应数据库字段
第二步:
找到 id="registeredServicesList" 修改allowedAttributes为
<property name="allowedAttributes">
<list>
<value>NAME</value>
<value>ROLE_ID</value>
</list>
</property>
cas客户端,服务端认证完成