单点登录解决方案-CAS

本文目标

  • 目标1:搭建单点登录服务端,开发单点登录客户端
  • 目标2:实现CAS 认证数据源设置
  • 目标3:更换CAS 登录页面
  • 目标4:掌握CAS与SpringSecurity集成
  • 目标5:完成用户中心单点登录功能

单点登录

  • 单点登录(Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一。SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。
  • 我们目前的系统存在诸多子系统,而这些子系统是分别部署在不同的服务器中,那么使用传统方式的session是无法解决的,我们需要使用相关的单点登录技术来解决。

单点登录解决方案-CAS_第1张图片

CAS

什么是CAS

  • CAS 是 Yale 大学发起的一个开源项目,旨在为 Web 应用系统提供一种可靠的单点登录方法,CAS 在 2004 年 12 月正式成为 JA-SIG 的一个项目。CAS 具有以下特点:
    • 【1】开源企业级单点登录解决方案
    • 【2】CAS Server 为需要独立部署的 Web 应用
    • 【3】CAS Client 支持非常多的客户端(这里指单点登录系统中的各个 Web 应用),包括 Java, .Net, PHP, Perl, Apache, uPortal, Ruby 等。

server和client

  • 从结构上看,CAS 包含两个部分: CAS Server 和CAS Client。
    • CAS Server :需要独立部署,主要负责对用户的认证工作;
    • CAS Client :负责处理对客户端受保护资源的访问请求,需要登录时,重定向到 CAS Server
  • 下图是CAS 最基本的协议过程:

单点登录解决方案-CAS_第2张图片

sso流程

  • SSO单点登录访问流程主要有以下步骤:
  1. 访问服务:SSO客户端发送请求访问应用系统提供的服务资源。
  2. 定向认证:SSO客户端会重定向用户请求到SSO服务器。
  3. 用户认证:用户身份认证。
  4. 发放票据:SSO服务器会产生一个随机的Service Ticket。
  5. 验证票据:SSO服务器验证票据Service Ticket的合法性,验证通过后,允许客户端访问服务。
  6. 传输用户信息:SSO服务器验证票据通过后,传输用户认证结果信息给客户端。

CAS服务端部署

  • Cas服务端其实就是一个war包。在cas-server-4.0.0-release\cas-server-4.0.0\modules目录下cas-server-webapp-4.0.0.war ,将其改名为cas.war放入tomcat目录下的webapps下。启动tomcat自动解压war包。浏览器输入http://localhost:8080/cas/login ,可看到登录页面

我们使用CAS时是无需编码的,一切需要根据我们项目作出调整的需求都可更改相应的配置文件来实现。

登录认证

  • 默认提供的通行证账号为casuser,密码Mellon,按此登录方可登录成功。此通行逻辑源于webapps/cas/WEB-INF/deployerConfigContext.xml文件中的配置:

    
        
            
            
        
    

 

你可以增加一个entry来增加一个通行证(如我增加了tom)。修改配置文件后别忘了重启tomcat以使其生效。

登出url

  • /logout为登出url,即请求localhost:8080/cas/logout即可注销当前浏览器在CAS中的登录。

端口修改

  • 如果我们不希望用8080端口访问CAS, 可以修改端口,需更改两处配置:

    • 打开tomcat 目录 conf\server.xml  找到下面的配置,更改端口号(如9100)

     

    • 修改CAS配置文件,修改webapps/cas/WEB-INF/cas.properties
    server.name=http://localhost:9100

     

去除https协议

CAS默认使用的是HTTPS协议,如果使用HTTPS协议需要SSL安全证书(需向特定的机构申请和购买) 。如果对安全要求不高或是在开发测试阶段,可使用HTTP协议。我们这里讲解通过修改配置,让CAS使用HTTP协议。

  • 修改cas的``WEB-INF/deployerConfigContext.xml`,找到下面的配置

 

 

​ 这里需要增加参数p:requireSecure="false",requireSecure属性意思为是否需要安全验证,即HTTPS,false为不采用

  • 修改cas的/WEB-INF/spring-configuration/ticketGrantingTicketCookieGenerator.xml,找到下面配置:

 

 

​ 参数p:cookieSecure="true",同理为HTTPS验证相关,TRUE为采用HTTPS验证,FALSE为不采用https验证。参数p:cookieMaxAge="-1",是cookie的最大生命周期,-1为无生命周期,即只在当前打开的窗口有效,关闭或重新打开其它窗口,仍会要求验证。可以根据需要修改为大于0的数字,比如3600等,意思是在3600秒内,打开任意窗口,都不需要验证。我们这里将cookieSecure改为false , cookieMaxAge 改为3600

  • 修改cas的WEB-INF/spring-configuration/warnCookieGenerator.xml,找到下面配置

 

 

​ 我们这里将cookieSecure改为false , cookieMaxAge 改为3600

CAS客户端入门小Demo

客户端工程1搭建

  1. 搭建工程引入依赖

    创建Maven工程 (war)casclient_demo1 引入cas客户端依赖并指定tomcat运行端口为9001

    
          
          
            org.jasig.cas.client  
            cas-client-core 
      3.3.3  
          		
        
            javax.servlet
            servlet-api
            2.5  
            provided
        
      
      
        
              
                org.apache.maven.plugins  
                maven-compiler-plugin  
                2.3.2  
                  
                    1.7  
                    1.7  
                  
              
            
                org.apache.tomcat.maven
                tomcat7-maven-plugin
                
                    
                    9001
                    
                    /
                
            
          
    

     

  2. 添加WEB-INF/web.xml,添加配置如下:



    
    
    
        org.jasig.cas.client.session.SingleSignOutHttpSessionListener
    
    
    
    
        CAS Single Sign Out Filter
        org.jasig.cas.client.session.SingleSignOutFilter
    
    
        CAS Single Sign Out Filter
        /*
    
    
    
    
        CASFilter
        org.jasig.cas.client.authentication.AuthenticationFilter
        
            casServerLoginUrl   
            http://localhost:9100/cas/login
        
        
            serverName
            
            http://localhost:9001
        
    
    
        CASFilter
        /*
    
    
    
    
        CAS Validation Filter
        org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter
        
            casServerUrlPrefix
            http://localhost:9100/cas
        
        
            serverName
            
            http://localhost:9001
        
    
    
        CAS Validation Filter
        /*
    
    
    
    
        CAS HttpServletRequest Wrapper Filter
        
            org.jasig.cas.client.util.HttpServletRequestWrapperFilter
        
    
    
        CAS HttpServletRequest Wrapper Filter
        /*
    
    
    
    
        CAS Assertion Thread Local Filter
        org.jasig.cas.client.util.AssertionThreadLocalFilter
    
    
        CAS Assertion Thread Local Filter
        /*
    

 

 

  1. 创建index.jsp
<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>


    
        
        一品优购
    
    
        欢迎来到一品优购,<%=request.getRemoteUser()%>
    

 

 

request.getRemoteUser()为获取远程登录名

客户端工程2搭建

  • 创建Maven工程 (war)casclient_demo2 引入cas客户端依赖并制定tomcat运行端口为9002
  • 创建web.xml,参照casclient_demo1 ,将serverName(cas客户端IP)的值改为http://localhost:9002,一共两处
  • 创建index.jsp ,内容显示“欢迎来到品优购”

单点登录测试

  • 启动cas服务部署的tomcat(9100)
  • 启动客户端工程1和客户端工程2
  • 地址栏输入http://localhost:9001/ 和http://localhost:9002/ ,地址均会跳转到CAS登录页
  • 输入用户名(casuser)和密码(Mellon)后,页面跳转回9002,再次访问9001也可以打开主页面。

单点登出

  • 访问:http://localhost:9100/cas/logout,再次访问9001和9002会发现都需要重新认证。
  • 我们可以将http://localhost:9100/cas/logout 加入到90019002工程的页面链接中以实现单点登出
欢迎来到一品优购,<%=request.getRemoteUser()%>。
点击退出

 

登出到指定url

  • 我们更希望退出登录后,能自动跳转到某个页面,那如何处理呢?

    • 修改cas系统(9100)的配置文件WEB-INF/cas-servlet.xml中的${cas.logout.followServiceRedirects:true}

     

  • 这样在cas客户端的登出url中加上回调URL即可

退出登录

 

CAS服务端数据源设置

需求分析

  • 我们现在让用户名密码从数据库用户表tb_user里做验证

配置数据源

  • 修改cas服务端中WEB-INFdeployerConfigContext.xml ,在末尾前添加如下配置

 

  


 

 

 

  • 然后在该文件的开头部分找到如下配置:

        
            
                
                
            
        

 

 

  • 其中这一配置是使用固定的用户名和密码进行认证。就像我们之前配的tom,123

    
        
            
                
                
            
        
    

     

  • 要想使用数据库表做动态认证,需要注释此行配置,改为我们添加的数据库认证处理器:

<1--  -->

 

 

需要注意的是,我们添加的c3p0、md5加密、根据数据源进行认证的dbAuthHandler需要引入3个依赖到WEB-INF/lib

  • c3p0-0.9.1.2.jar
  • cas-server-support-jdbc-4.0.0.jar
  • mysql-connector-java-5.1.32.jar
  • 重启tomcat,使用数据库tb_user表中的数据做登录测试

CAS服务端界面改造

需求分析

  • 我们现在动手将CAS默认的登录页更改为自己项目的登陆页

改头换面

  • 拷贝资源
    • 品优购的登陆页login.html拷贝到cas系统下webapp\cas\WEB-INF\view\jsp\default\ui 目录下
    • css js等文件夹拷贝到 webapp/cas目录下
    • 将原来的casLoginView.jsp 改名为casLoginView-origin.jsp(留作参照),将login.html改名为casLoginView.jsp

修改页面

  • 修改casLoginView.jsp (参照casLoginView-origin.jsp

    • 添加jsp指令
    <%@ page pageEncoding="UTF-8" %>
    <%@ page contentType="text/html; charset=UTF-8" %>
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
    <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
    <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>

     

    • 修改form标签
    
    ......
    

     

    • 修改用户名框

     

    • 修改密码框

     

    • 修改登陆按钮
    
    
    
    

     

错误提示

  • 在表单内加入登录失败提示框

 

 

  • 测试:输入错误的用户名和密码,提示是英文。这个提示信息是在cas\WEB-INF\classes目录下的messages.properties文件中 :

    authenticationFailure.AccountNotFoundException=Invalid credentials.
    authenticationFailure.FailedLoginException=Invalid credentials.

     

  • 设置国际化为zn_CN  ,修改WEB-INF\cas-servlet.xml

     

  • 我们在WEB-INF/classes/messages_zh_CN.properties下增加如下配置(中文转码为UTF-8):

    authenticationFailure.AccountNotFoundException=\u7528\u6237\u4E0D\u5B58\u5728.
    authenticationFailure.FailedLoginException=\u5BC6\u7801\u9519\u8BEF.

     

    第一个是用户名不存在时的错误提示

    第二个是密码错误的提示

CAS客户端与SpringSecurity集成

Spring Security测试工程搭建

  • (1)建立Maven项目casclient_demo3 ,引入spring依赖和spring secrity 相关依赖 ,tomcat端口设置为9003

    
        
            org.springframework
            spring-core
            ${spring.version}
        
        
            org.springframework
            spring-web
            ${spring.version}
        
    
        
            org.springframework
            spring-webmvc
            ${spring.version}
        
    
        
            org.springframework
            spring-context-support
            ${spring.version}
        
    
        
            org.springframework.security
            spring-security-web
            4.1.0.RELEASE
        
    
        
            org.springframework.security
            spring-security-config
            4.1.0.RELEASE
        
    
        
            javax.servlet
            servlet-api
            2.5
            provided
        
    
        
        
            org.jasig.cas.client
            cas-client-core
            3.3.3
        
    
    
    
        
            
                org.apache.tomcat.maven
                tomcat7-maven-plugin
                
                    
                    9003
                    
                    /
                
            
        
    

     

  • (2)建立web.xml

    
        contextConfigLocation
        classpath:spring/spring-security.xml
    
    
        
            org.springframework.web.context.ContextLoaderListener
        
    
    
    
        springSecurityFilterChain
        org.springframework.web.filter.DelegatingFilterProxy
    
    
        springSecurityFilterChain
        /*
    

     

  • (3)创建配置文件spring-security.xml

    • spring-security.xml
    
    
    
    	
    	
    		
    		
    		
    		
    		
    			
    		
    		
    	
    
    	
    	
    		
    			
    				
    			
    		
    	
    
    

     

  • 添加/login.html/index.html测试SpringSecurity搭建是否成功

    • login.html

     

    • index.html
    欢迎光临

     

    • 访问 http://localhost:9003/index.html ,自动跳转到登录页,输入admin、admin,登录成功,SpringSecurity搭建完成。

Spring Security与 CAS集成

  • (1)引入CAS客户端、SpringSecurity整合CAS的依赖

      
    	   org.springframework.security  
    	   spring-security-cas  
    	   4.1.0.RELEASE  
         
      
            org.jasig.cas.client  
            cas-client-core  
            3.3.3  
              
                  
                    org.slf4j  
                    log4j-over-slf4j  
                  
              
     

     

  • (2)修改spring-security.xml如下(把9001中web.xml中的配置移到了spring配置,并把SpringSecurity认证的提供指定为cas):

    
    
    
        
          
               
              
                       
                  
              
              
        
    
    
        
    
              
              
              
           
    
          
              
            
          
    
    
    
    
          
              
          
    
        
        
            
            
        
    
        
        
    
            
              
                  
                      
                  
              
    
            
              
    
            
              
                  
                      
                  
              
             
         
    
        
          
    
    
    
         
                  
          
    
              
    
              
                  
              
    
              
    
          
      
    

     

  • (3)创建UserDetailsServiceImpl 

/**
 * 认证类
 */
public class UserDetailServiceImpl implements UserDetailsService {
	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //拿用户名到数据库查询用户的事CAS系统帮你做了
        
        //构建角色集合
		List authorities=new ArrayList();
        //TODO 应该从数据库查询该用户权限的,这里作为demo简化,直接赋值
		authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
		return new User(username, ""  , authorities);		
	}
}

 

 

这个类的主要作用是在登陆后得到用户名,可以根据用户名查询角色或执行一些逻辑。 如通过 SecurityContextHolder获取用户名。

  • (4)访问 localhost:9003 ,页面跳转到CAS服务端登录页面,输入数据库表中的用户登录成功后重定向到 localhost:9003,至此整合成功。

获取登录名

  • 我们在处理后端逻辑需要获得登录名,那么如何获取单点登录的用户名呢? 其实UserDetailServiceImpl已经帮我们保存了登录名,只需建立一个Controller并通过SecurityContextHolder获取返回给前端。

退出登录

  • 要想退出登录(http://localhost:9100/cas/logout)后调往指定页面,则需修改spring-security.xml ,如下面调往http://localhost:9003/index2.html:

    ...
      
              
              
                  
              
    
        	
              
    

     

  • 在页面上添加链接,退出登录将跳往index2.html

    退出登录

     

  • 创建index2.html,将index2.html设置为可匿名访问

     

附录A. Spring Security 内置过滤器表

别名 Filter
CHANNEL_FILTER ChannelProcessingFilter
SECURITY_CONTEXT_FILTER SecurityContextPersistenceFilter
CONCURRENT_SESSION_FILTER ConcurrentSessionFilter
LOGOUT_FILTER LogoutFilter
X509_FILTER X509AuthenticationFilter
PRE_AUTH_FILTER AstractPreAuthenticatedProcessingFilter 的子类
CAS_FILTER CasAuthenticationFilter
FORM_LOGIN_FILTER UsernamePasswordAuthenticationFilter
BASIC_AUTH_FILTER BasicAuthenticationFilter
SERVLET_API_SUPPORT_FILTER SecurityContextHolderAwareRequestFilter
JAAS_API_SUPPORT_FILTER JaasApiIntegrationFilter
REMEMBER_ME_FILTER RememberMeAuthenticationFilter
ANONYMOUS_FILTER AnonymousAuthenticationFilter
SESSION_MANAGEMENT_FILTER SessionManagementFilter
EXCEPTION_TRANSLATION_FILTER ExceptionTranslationFilter
FILTER_SECURITY_INTERCEPTOR FilterSecurityInterceptor
SWITCH_USER_FILTER SwitchUserFilter

 


更多学习资源请上白玉搜一搜

你可能感兴趣的:(java)