天天看点

pentaho 单点登录 cas 单点登录,平台不需添加用户帐号

    各种baidu、google、biying之后实现了pentaho的cas单点登录,but,都有一个致命的问题:只有在pentaho中存在的用户才能正常登录。 问题放了一段时间,可最终还是要解决的。花了几天时间,总算解决了:pentaho中用户不存在也可登录,只要cas服务器登录成功即可。     如果有兴趣知道怎么实现的可以往下慢慢看,只想快点搞定的可以直接去我的百度云盘下载附件,里面有安装手册,直接包含了如何配置cas单点登录。 云盘地址:http://pan.baidu.com/s/1dFMGwoT 最近项目中用到pentaho这个BI平台,用的是ce 6.1.0.1-196社区版。相信很多做pentaho单点登录的都已经配置过很多次cas了吧,如何配置就不再赘述了,挑重点讲下。     截取cas配置文件里面才一段代码,相信很多人对这段配置不陌生吧!

<property name="userDetailsService">
     <pen:bean class="org.springframework.security.userdetails.UserDetailsService" />
</property>
           

注意 userDetailsService,这个是单点登录获取用户的,顶层接口只有一个方法:“loadUserByUsername”,更具用户名获取用户的,在pentaho里面有很多不同的实现,其中有一个是我们要用到的 org.pentaho.platform.security.userroledao.service.UserRoleDaoUserDetailsService,在这里我直接用如下配置替代了(有些配置 userDetailsService方式是和我一样的)

<property name="userDetailsService" ref="userDetailsService"/>
           

经过各种配置文件的找,发现userDetailsService的具体实现类配置在了“applicationContext-spring-security-jackrabbit.xml”这配置文件里面,具体路径配置过的人应该知道去那里找了。里面有这么一段xml配置

<bean id="userDetailsService" class="org.pentaho.platform.security.userroledao.service.UserRoleDaoUserDetailsService">
    <property name="userRoleDao">
      <ref bean="userRoleDaoTxn" />
    </property>
    ......
           

这里才是关键,为了实现单点登录,我更改了userDetailsService的具体实现类如下:

<bean id="userDetailsService" class="com.cn.custom.UserRoleDaoUserDetailsService">
    <property name="userRoleDao">
      <ref bean="userRoleDaoTxn" />
    </property>
    ......
           

“com.cn.custom.UserRoleDaoUserDetailsService”则是我在“org.pentaho.platform.security.userroledao.service.UserRoleDaoUserDetailsService”的基础上更改了点代码,判断,原始代码是加载用户,如果不存在就抛出异常,我却在这创建用户,不再抛异常了。

附上com.cn.custom.UserRoleDaoUserDetailsService源码:

/*!
 * This program is free software; you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
 * Foundation.
 *
 * You should have received a copy of the GNU Lesser General Public License along with this
 * program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
 * or from the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Lesser General Public License for more details.
 *
 * Copyright (c) 2002-2013 Pentaho Corporation..  All rights reserved.
 */

package com.cn.custom;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.pentaho.platform.api.engine.IPentahoSession;
import org.pentaho.platform.api.engine.security.userroledao.IPentahoRole;
import org.pentaho.platform.api.engine.security.userroledao.IPentahoUser;
import org.pentaho.platform.api.engine.security.userroledao.IUserRoleDao;
import org.pentaho.platform.api.engine.security.userroledao.UncategorizedUserRoleDaoException;
import org.pentaho.platform.api.mt.ITenant;
import org.pentaho.platform.core.mt.Tenant;
import org.pentaho.platform.engine.core.system.PentahoSessionHolder;
import org.pentaho.platform.engine.core.system.PentahoSystem;
import org.pentaho.platform.repository2.unified.jcr.JcrTenantUtils;
import org.pentaho.platform.security.userroledao.messages.Messages;
import org.pentaho.reporting.libraries.base.util.StringUtils;
import org.springframework.dao.DataAccessException;
import org.springframework.security.GrantedAuthority;
import org.springframework.security.GrantedAuthorityImpl;
import org.springframework.security.userdetails.User;
import org.springframework.security.userdetails.UserDetails;
import org.springframework.security.userdetails.UserDetailsService;
import org.springframework.security.userdetails.UsernameNotFoundException;
import org.springframework.util.Assert;

/**
 * A <code>UserDetailsService</code> that delegates to an {@link IUserRoleDao} to load users by username.
 * 
 * @author mlowery
 */
public class UserRoleDaoUserDetailsService implements UserDetailsService {

	// ~ Static fields/initializers
	// ======================================================================================

	// ~ Instance fields
	// =================================================================================================

	private String rolePrefix = "ROLE_"; //$NON-NLS-1$

	private IUserRoleDao userRoleDao;

	/**
	 * A default role which will be assigned to all authenticated users if set
	 */
	private GrantedAuthority defaultRole;

	private String defaultRoleString;

	// ~ Constructors
	// ====================================================================================================

	// ~ Methods
	// =========================================================================================================

	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
		final boolean ACCOUNT_NON_EXPIRED = true;
		final boolean CREDS_NON_EXPIRED = true;
		final boolean ACCOUNT_NON_LOCKED = true;

		IPentahoUser user;
		try {
			if (userRoleDao == null) {
				userRoleDao = PentahoSystem.get(IUserRoleDao.class, "userRoleDaoProxy", PentahoSessionHolder.getSession());
			}
			user = userRoleDao.getUser(null, username);
		} catch (UncategorizedUserRoleDaoException e) {
			throw new UserRoleDaoUserDetailsServiceException(
					Messages.getInstance().getString("UserRoleDaoUserDetailsService.ERROR_0003_DATA_ACCESS_EXCEPTION"), e); //$NON-NLS-1$
		}

		if (user == null) {
			ITenant tenant = new Tenant("/pentaho/tenant0", true);
			String password = "123456";
			String description = "cas user";
			String[] roles = new String[0];
			user = userRoleDao.createUser(tenant, username, password, description, roles);

			// throw new UsernameNotFoundException(
			// Messages.getInstance().getString("UserRoleDaoUserDetailsService.ERROR_0001_USER_NOT_FOUND"));
			// //$NON-NLS-1$
		}
		// convert IPentahoUser to a UserDetails instance
		List<IPentahoRole> userRoles = userRoleDao.getUserRoles(null, username);
		int authsSize = userRoles != null ? userRoles.size() : 0;
		GrantedAuthority[] auths = new GrantedAuthority[authsSize];
		int i = 0;
		for (IPentahoRole role : userRoles) {
			auths[i++] = new GrantedAuthorityImpl(role.getName());
		}

		List<GrantedAuthority> dbAuths = new ArrayList<GrantedAuthority>(Arrays.asList(auths));
		addCustomAuthorities(user.getUsername(), dbAuths);

		// Store the Tenant ID in the session
		IPentahoSession session = PentahoSessionHolder.getSession();
		String tenantId = (String) session.getAttribute(IPentahoSession.TENANT_ID_KEY);
		if (tenantId == null) {
			ITenant tenant = JcrTenantUtils.getTenant(username, true);
			session.setAttribute(IPentahoSession.TENANT_ID_KEY, tenant.getId());
		}

		if (!StringUtils.isEmpty(defaultRoleString)) {
			defaultRole = new GrantedAuthorityImpl(defaultRoleString);
		}

		if (defaultRole != null && !dbAuths.contains(defaultRole)) {
			dbAuths.add(defaultRole);
		}

		if (dbAuths.size() == 0) {
			throw new UsernameNotFoundException(
					Messages.getInstance().getString("UserRoleDaoUserDetailsService.ERROR_0002_NO_AUTHORITIES")); //$NON-NLS-1$
		}

		GrantedAuthority[] arrayAuths = dbAuths.toArray(new GrantedAuthority[dbAuths.size()]);

		return new User(user.getUsername(), user.getPassword(), user.isEnabled(), ACCOUNT_NON_EXPIRED, CREDS_NON_EXPIRED,
				ACCOUNT_NON_LOCKED, arrayAuths);
	}

	/**
	 * Allows subclasses to add their own granted authorities to the list to be returned in the <code>User</code>.
	 * 
	 * @param username
	 *            the username, for use by finder methods
	 * @param authorities
	 *            the current granted authorities, as populated from the <code>authoritiesByUsername</code> mapping
	 */
	protected void addCustomAuthorities(String username, List authorities) {
	}

	/**
	 * Allows a default role prefix to be specified. If this is set to a non-empty value, then it is automatically
	 * prepended to any roles read in from the db. This may for example be used to add the <code>ROLE_</code> prefix
	 * expected to exist in role names (by default) by some other Spring Security framework classes, in the case that
	 * the prefix is not already present in the db.
	 * 
	 * @param rolePrefix
	 *            the new prefix
	 */
	public void setRolePrefix(String rolePrefix) {
		if (rolePrefix == null) {
			this.rolePrefix = ""; //$NON-NLS-1$
		} else {
			this.rolePrefix = rolePrefix;
		}
	}

	public String getRolePrefix() {
		return rolePrefix;
	}

	/**
	 * A data access exception specific to a <code>IUserRoleDao</code>-based <code>UserDetailsService</code>.
	 */
	protected class UserRoleDaoUserDetailsServiceException extends DataAccessException {

		private static final long serialVersionUID = -3598806635515478946L;

		public UserRoleDaoUserDetailsServiceException(String msg) {
			super(msg);
		}

		public UserRoleDaoUserDetailsServiceException(String msg, Throwable cause) {
			super(msg, cause);
		}

	}

	public void setUserRoleDao(IUserRoleDao userRoleDao) {
		this.userRoleDao = userRoleDao;
	}

	/**
	 * The default role which will be assigned to all users.
	 * 
	 * @param defaultRole
	 *            the role name, including any desired prefix.
	 */
	public void setDefaultRole(String defaultRole) {
		Assert.notNull(defaultRole);
		this.defaultRoleString = defaultRole;
		this.defaultRole = new GrantedAuthorityImpl(defaultRole);
	}
}
           

然后把对应的class文件发布到pentaho的tomcat的pentaho工程的classes目录下。

在pentaho-spring-beans.xml里面添加映入cas的配置是必须的:

......
  <import resource="applicationContext-pentaho-security-jackrabbit.xml" />
  <import resource="applicationContext-spring-security-jackrabbit.xml" />
  <import resource="applicationContext-pentaho-security-jdbc.xml" />
  <import resource="applicationContext-spring-security-jdbc.xml" />

  <!-- cas configuration begin -->
  <import resource="applicationContext-spring-security-cas.xml" />
  <!-- cas configuration end -->
  ......
           

然后替换修改过文件,添加cas-client-core-3.1.10.jar和spring-security-cas-client-2.0.5.RELEASE.jar(jar包版本更具自己实际情况添加)到tomcat pentaho工程的lib目录下。

到这里pentaho的单点登录完成,再也不用一个一个的添加帐号密码了。

无偿分享,copy请给我的引用个链接,算是对得起我手敲了这么多字。有更好解决方法的欢迎分享。

继续阅读