单点登录CAS与Spring Security集成(数据库验证,向客户端发送更多信息)

准备工作

CAS server从网上直接下载下来,里面有一个cas-server-webapp的工程,使用Maven命令构建,导入到Eclipse中,便可以直接使用,cas server我使用的是3.5.2版本。客户端,我是使用以前的工程,只要是Web工程就行,cas-client使用的3.2.1,Spring Security使用的是3.1.4,记得Spring Security的3.1.2版本和CAS集成时,当需要CAS Server传比较多的信息给客户端时,客户端的Spring Security会解析出错(如果木有记错的话)

**PS:**无使用HTTPS协议,需要对CAS Server的配置做改动,具体后面详述

服务端(CAS Server)

服务端部署在8080端口

使用HTTP协议

CAS Server完全使用的是CAS官方的工程,名为cas-server-webapp,导入到Eclipse中之后,就是一普通的Web工程,官方的Demo是需要HTTPS的,此篇讨论的就是普通的HTTP,首先修改ticketGrantingTicketCookieGenerator.xml和warnCookieGenerator.xml这两个文件,将p:cookieSecure属性值设置为false

使用数据库的验证方式登录

使用数据库的验证方式登录,需要修改几个地方,一是配置文件,二是编写自己的数据库查询的类(这个类在3.5.2中提供了,可以通过配置文件实现),也可以自己实现该类。

配置文件

需要修改deployerConfigContext.xml,使用我们自己定义的类验证,配置文件如下:





	
	
		
		
		
		
		
			
				



					
					
				
				
			
		

		
		
			
				
				
				



				
				
				
			
		
	
	
	
	
	
	
		
	

	
    

    
        
    
	
	
	
		
			
				
				 
				
			
		
	
	
	
	





        	









                    
                    


        

  
  
  
    
      
        
        
        
      
    
  

数据库访问类

该类根据输入的用户名,去查询数据,并对密码进行验证

package com.wds.security.cas;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.jasig.cas.authentication.handler.AuthenticationException;
import org.jasig.cas.authentication.handler.support.AbstractUsernamePasswordAuthenticationHandler;
import org.jasig.cas.authentication.principal.UsernamePasswordCredentials;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.security.authentication.dao.SaltSource;
import org.springframework.security.authentication.encoding.PasswordEncoder;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;

import com.wds.security.pojo.BaseUser;
import com.wds.security.pojo.BaseUserDetail;

public class UsernamePasswordJDBCAuthenticationHandler extends
		AbstractUsernamePasswordAuthenticationHandler {

	private JdbcTemplate jdbcTemplate;
	
	private PasswordEncoder passEncoder;
	
	private SaltSource saltSource;
	
	@Override
	protected boolean authenticateUsernamePasswordInternal(
			UsernamePasswordCredentials credentials)
			throws AuthenticationException {
		final String username = credentials.getUsername();
		final String password = credentials.getPassword();
		
		String sql = " select * from  base_user where status = 1 and user_account ='" + username + "'";
		BaseUser baseUser = jdbcTemplate.queryForObject(sql, null, new RowMapper(){
			@Override
			public BaseUser mapRow(ResultSet rs, int rowNum)
					throws SQLException {
				BaseUser baseuser = new BaseUser();
				baseuser.setCode(rs.getString("code"));
				baseuser.setUserAccount(rs.getString("user_account"));
				baseuser.setUserPassword(rs.getString("user_password"));
				baseuser.setUserName(rs.getString("user_name"));
				return baseuser;
			}
			
		});
		
		List auth = new ArrayList();
		GrantedAuthority ga = new SimpleGrantedAuthority("admin");
		auth.add(ga);
		
		BaseUserDetail user = new BaseUserDetail(username, baseUser.getUserName(), baseUser.getUserPassword(),  baseUser.getCode(), true, true, true, true, auth);
		
		if(user != null){
			//验证密码
			String encodePassword = this.passEncoder.encodePassword(password, this.saltSource.getSalt(user));
			if(encodePassword.equals(user.getPassword())){
				return true;
			}
		}
		return false;
	}

	public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
		this.jdbcTemplate = jdbcTemplate;
	}
	
	public void setPassEncoder(PasswordEncoder passEncoder) {
		this.passEncoder = passEncoder;
	}

	public void setSaltSource(SaltSource saltSource) {
		this.saltSource = saltSource;
	}

}
另外还有一个加密使用的类如下:

package com.wds.security.cas;

import org.jasig.cas.authentication.handler.PasswordEncoder;
import org.springframework.security.authentication.dao.SaltSource;
import org.springframework.security.authentication.encoding.MessageDigestPasswordEncoder;
import org.springframework.security.core.userdetails.UserDetails;

public class MD5PassworEncoder extends MessageDigestPasswordEncoder implements
		PasswordEncoder {

	private SaltSource saltSource;

	private UserDetails user;

	public MD5PassworEncoder(String algorithm) {
		super("MD5");
	}

	@Override
	public String encode(String password) {
		return encodePassword(password, this.saltSource.getSalt(user));
	}

	public void setSaltSource(SaltSource saltSource) {
		this.saltSource = saltSource;
	}

	public void setUser(UserDetails user) {
		this.user = user;
	}

}
当然,还有一些数据库的配置,文中不再列出了

传送更多的信息

在做单点时,如果是默认配置,只能传输用户名到客户端,现希望可以传送更多的信息给客户端,例如,用户拥有的权限信息,可以传给客户,基于以上的配置,需要增加一个类,代码如下:
package com.wds.security.cas;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.jasig.cas.authentication.principal.Credentials;
import org.jasig.cas.authentication.principal.CredentialsToPrincipalResolver;
import org.jasig.cas.authentication.principal.Principal;
import org.jasig.cas.authentication.principal.SimplePrincipal;
import org.jasig.cas.authentication.principal.UsernamePasswordCredentials;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;

public class BaseUsernamePasswordCredentialsToPrincipalResolver implements
		CredentialsToPrincipalResolver {
	
	private static final Logger logger = LoggerFactory.getLogger(BaseUsernamePasswordCredentialsToPrincipalResolver.class);
	
	private JdbcTemplate jdbcTemplate;
	
	public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
		this.jdbcTemplate = jdbcTemplate;
	}

	@Override
	public Principal resolvePrincipal(Credentials credentials) {
		UsernamePasswordCredentials up = (UsernamePasswordCredentials) credentials;

		// 获取登录帐户
		logger.debug("登录用户:" + up.getUsername());
//		System.out.println(up.getPassword());
		final Map attr = new HashMap();

		String sql = "select resource_url from v_user_role_resources where user_account ='" + up.getUsername() + "'";
		
		List list = jdbcTemplate.queryForList(sql, String.class);
		attr.put(up.getUsername(), list);
		
		Principal p = new SimplePrincipal(up.getUsername(), attr);
		return p;
	}

	@Override
	public boolean supports(Credentials credentials) {
		return credentials != null
				&& UsernamePasswordCredentials.class
						.isAssignableFrom(credentials.getClass());
	}

}
此外,还需要修改验证成功的JSP界面casServiceValidationSuccess.jsp,代码如下:
<%--

    Licensed to Jasig under one or more contributor license
    agreements. See the NOTICE file distributed with this work
    for additional information regarding copyright ownership.
    Jasig licenses this file to you under the Apache License,
    Version 2.0 (the "License"); you may not use this file
    except in compliance with the License.  You may obtain a
    copy of the License at the following location:

      http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing,
    software distributed under the License is distributed on an
    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    KIND, either express or implied.  See the License for the
    specific language governing permissions and limitations
    under the License.

--%>
<%@ page session="false" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>

	
		${fn:escapeXml(assertion.chainedAuthentications[fn:length(assertion.chainedAuthentications)-1].principal.id)}
		
			${pgtIou}
		
		
			
				
					${fn:escapeXml(proxy.principal.id)}
				
			
		
		
		
			
				
					
						
							
								${fn:escapeXml(v)}
							
						
						
							${fn:escapeXml(attr.value)}
						
					
				
			
		
	

至此,服务端配置完成,

客户端

客户端部署在8083端口,只有一个Spring-Security的配置文件,文件内容如下:




	SpringSecurity

	
		
	

	
	
	
	
	
	
	
	
	
	
	
	

	
	
		

		
		

		
		
		
		
			
		
		
		
		
		
		
		
	

	
	
		
		
		
	

	
	
	

	
	

	
	

	
	
		
	

	
	
		
	

	
	
		
		
	
	
	
		
		
	

	
	
		
		
	

	
	
		
		
		
	

	
	
	
		
		
	

	
	
		
	

	
		
	

	
		
		
		
			
				
			
		
		
	

	
		
			
		
	
	
	


配置文件中还有其它配置,是用来验证权限的,重点关注和CAS相类的配置即可

Spring Security还有别外的一种配置,在Spring Security上面有提供,是pre开头的配置方式

测试

在服务端的casGenericSuccess.jsp文件中,增加一个连接,连接到客户端,即可。






你可能感兴趣的:(Java,Spring)