您的位置:首页 > 其它

CAS sso配置

2016-07-19 16:14 204 查看
最近在研究sso单点登录的问题,研究了网上许多案例以及代码,发现总是有很大的差别,最后通过官网下载,才发现cas3 与 cas 4 的配置存在区别,这就是差别很大的原因了。
官网地址如下: https://www.apereo.org/search/node/cas
下面只针对cas4进行整理吧,因为cas4 相对于cas3 来说,是有增无减了。
1.下载
地址http://downloads.jasig.org/
cas-server-4.0.0-release.tar.gz
cas-client-3.3.3-release.tar.gz

2.配置Sever端
解压cas-server-4.0.0,将其中module/cas-server-webapp-4.0.0.war复制到Tomcat的webapps目录下,重命名为cas.war,启动Tomcat解开压缩
启动tomcat
http://localhost:8080/cas,进入登录页面。 默认用户为casuser/Mellon,登录成功即启动正常,cas3的无默认用户,只需用户名密码一直即可。

2.1设置利用数据库来验证用户

需依赖:c3p0-0.9.1.2.jar,mysql-connector-java-5.1.21.jar,cas-server-support-jdbc-4.0.0.jar,cas-server-support-ldap-4.0.0.jar
修改 deployerConfigContext.xml

1)更换验证方式

<!--
<bean id="primaryAuthenticationHandler"
class="org.jasig.cas.authentication.AcceptUsersAuthenticationHandler">
<property name="users">
<map>
<entry key="casuser" value="Mellon"/>
</map>
</property>
</bean>
-->

<!-- Define the DB Connection -->
<bean id="dbAuthHandler" class="org.jasig.cas.authentication.handler.DefaultPasswordEncoder"
p:dataSource-ref="dataSource"
p:sql="select passwd from users where name=?" />

<!-- 使用dataSource-->
<bean id="dataSource"
class="com.mchange.v2.c3p0.ComboPooledDataSource"
p:driverClass="com.mysql.jdbc.Driver"
p:jdbcUrl="jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf-8"
p:user="root"
p:password="123" />
2)更换handler验证方式
<bean id="authenticationManager" class="org.jasig.cas.authentication.PolicyBasedAuthenticationManager">
<constructor-arg>
<map>
<entry key-ref="proxyAuthenticationHandler" value-ref="proxyPrincipalResolver" />
<entry key-ref="dbAuthHandler" value-ref="primaryPrincipalResolver" />
<!--本来使用primaryAuthenticationHandler,现在使用dbAuthHandler -->
<!-- <entry key-ref="primaryAuthenticationHandler" value-ref="primaryPrincipalResolver" /> -->
</map>
</constructor-arg>
注释了原来的默认用户,使用数据库替代,新建数据库test,暂时没有使用md5加密,数据库test的users表直接设置passwd和name即可
3)使用md5加密,密码校验类自定义实现
<bean id="dbAuthHandler" class="com.test.cas.MyQueryDatabaseAuthenticationHandler"
p:dataSource-ref="dataSource"
p:sql="select passwd from users where name=?"
p:passwordEncoder-ref="passwordEncoder"/>

<bean id="passwordEncoder" class="org.jasig.cas.authentication.handler.DefaultPasswordEncoder"
c:encodingAlgorithm="md5"
p:characterEncoding="UTF-8" />
4)密码校验类自定义实现

public class MyQueryDatabaseAuthenticationHandler extends AbstractJdbcUsernamePasswordAuthenticationHandler{
@NotNull
private String sql;

@Override
protected HandlerResult authenticateUsernamePasswordInternal(UsernamePasswordCredential credential)throws GeneralSecurityException, PreventedException {
final String username = credential.getUsername();

final String encryptedPassword = this.getPasswordEncoder().encode(credential.getPassword()+"{"+username+"}");
try {
final String dbPassword = getJdbcTemplate().queryForObject(this.sql, String.class, username);
if (!dbPassword.equals(encryptedPassword)) {
throw new FailedLoginException("Password does not match value on record.");
}
} catch (final IncorrectResultSizeDataAccessException e) {
if (e.getActualSize() == 0) {
throw new AccountNotFoundException(username + " not found with SQL query");
} else {
throw new FailedLoginException("Multiple records found for " + username);
}
} catch (final DataAccessException e) {
throw new PreventedException("SQL exception while executing query for " + username, e);
}
return createHandlerResult(credential, new SimplePrincipal(username), null);
}

public void setSql(final String sql) {
this.sql = sql;
}
}


因为这里的密码采用了 密码{用户名} 加密的方式,所以使用了自定义的密码校验,重启,测试通过

3.配置Client端
3.1 普通方式
新建testweb项目,在Client工程WEB-INF/lib下添加cas-client-core-3.2.1.jar包
修改web.xml如下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>testWeb1</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>

<!-- ======================== 单点登录/登出 ======================== -->

<!-- 定义serverName,一个全局变量 -->
<context-param>
<param-name>serverName</param-name>
<param-value>http://localhost:8080</param-value>
</context-param>

<!-- 该过滤器用于实现单点登出功能,可选配置。 -->
<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:8080/cas/login</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:8080/cas</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>
<!-- ======================== 单点登录/登出结束 ======================== -->

<servlet>
<servlet-name>HelloWorldExample</servlet-name>
<servlet-class>servlets.HelloWorld</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloWorldExample</servlet-name>
<url-pattern>HelloWorldExample</url-pattern>
</servlet-mapping>

</web-app>

这里配置了HelloWorld servlet 来配合测试
public class HelloWorld extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
{
AttributePrincipal principal = (AttributePrincipal) request.getUserPrincipal();
String username = principal.getName();
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head>");
out.println("<title>Hello World</title>");
out.println("</head>");
out.println("<body>");
out.println("<h1>Hello World!"+username+"</h1>");
out.println("</body>");
out.println("</html>");
}
}
访问localhost:8080/testWeb1/HelloWorldExample ,首次访问任一页面就会跳转到

https://localhost:8080/cas/login进行认证

3.2 spring 方式
这里采用spring security 与cas结合的方式
<!-- entry-point-ref入口点的意思,当捕捉到尚未登陆,尝试访问其他url时,会自动跳到入口点 -->
<http  auto-config="true" entry-point-ref="casAuthenticationEntryPoint" >
<custom-filter ref="myFilter"   before="FILTER_SECURITY_INTERCEPTOR" />

<!-- CasAuthenticationFilter总是监听/j_spring_cas_security_check请求 -->
<!-- 认证请求将被配置的AuthenticationManager处理 -->
<custom-filter position="CAS_FILTER" ref="casAuthenticationFilter" />

<access-denied-handler ref="accessDeniedHandler"></access-denied-handler>
</http>

<beans:bean id="casAuthenticationEntryPoint" class="org.springframework.security.cas.web.CasAuthenticationEntryPoint">
<beans:property name="loginUrl" value="http://sso.test.com/login"></beans:property>
<!-- service指定了回调url,当认证成功时,会跳回到这 -->
<beans:property name="serviceProperties" ref="serviceProperties"></beans:property>
</beans:bean>

<!-- service指定了回调url,当认证成功时,会跳回到这 -->
<beans:bean id="serviceProperties" class="org.springframework.security.cas.ServiceProperties">
<beans:property name="service" value="http://localhost:8080/testweb/j_spring_cas_security_check"></beans:property>
<beans:property name="sendRenew" value="false"></beans:property>
</beans:bean>

<!--当sso验证成功后,所有请求会在此处理 -->
<beans:bean id="casAuthenticationProvider" class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
<beans:property name="authenticationUserDetailsService" ref="authenticationUserDetailsService"/>
<beans:property name="serviceProperties" ref="serviceProperties"></beans:property>
<!-- 校验服务票据 -->
<!-- Cas20TicketValidator 解析从CAS服务器收到的XML,它给CasAuthenticationProvider 返回一个TicketResponse,其中包含用户名和代理列表 -->
<!-- 接下来将请求AuthenticationUserDetailsService 去加载应用于包含在Assertion中用户的GrantedAuthority 对象 -->
<beans:property name="ticketValidator">
<beans:bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator">
<!-- 配置cas服务器 -->
<beans:constructor-arg index="0" value="http://sso.test.com/" />
</beans:bean>
</beans:property>
<beans:property name="key" value="cas" />
</beans:bean>

<!-- authorities对应 CAS server的 登录属性, 在此设置到spirng security中,用于spring security的验证 -->
<beans:bean id="authenticationUserDetailsService" class="com.test.security.MyGrantedAuthorityFromAssertionAttributesUserDetailsService">
</beans:bean>

<authentication-manager alias="authenticationManager">
<authentication-provider ref="casAuthenticationProvider"></authentication-provider>
</authentication-manager>

<!-- cas 认证失败控制器 -->
<beans:bean id="authenticationFailureHandler"  class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
<beans:property name="defaultFailureUrl" value="/login?error=error" />
</beans:bean>
<!-- cas 认证成功控制器 -->
<beans:bean id="authenticationSuccessHandler"  class="com.test.AuthenticationSuccessHandler">
<beans:property name="defaultTargetUrl" value="/" />
</beans:bean>

<beans:bean id="casAuthenticationFilter" class="org.springframework.security.cas.web.CasAuthenticationFilter">
<beans:property name="authenticationManager" ref="authenticationManager"></beans:property>
<beans:property name="authenticationFailureHandler" ref="authenticationFailureHandler" />
<beans:property name="authenticationSuccessHandler" ref="authenticationSuccessHandler" />
<beans:property name="filterProcessesUrl" value="/j_spring_cas_security_check" />
</beans:bean>


具体spring security 与cas 的配置结合,可参考 http://5148737.blog.51cto.com/5138737/1827795
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  server sso cas