天天看點

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請給我的引用個連結,算是對得起我手敲了這麼多字。有更好解決方法的歡迎分享。

繼續閱讀