saiku集成CAS

        最近一直在研究saiku如何集成公司的单点登录系统,通过google、百度搜集查阅了大量的相关资料,并和网友讨论最终在公司内部集成完成,最终测试上线;现将这一过程中的经验记录下来,分享给需要的朋友....
        saiku集成CAS这一过程其实我们可以简单的理解为:用户CAS验证后,我们获取到用户名,并拿该用户登陆saiku,若该用户有saiku访问权限就登陆saiku,反之则不能登陆,返回无权限提示,整个过程有以下几个步骤:
        1.修改web.xml配置:修复filter拦截过程,加入CAS系统配置
        2.编写filter:获取用户名,免密码无缝登陆saiku
        3.退出登陆:注销saiku及CAS的session

修改web.xml配置

        首先,注释saiku拦截filter配置,当我们在浏览器中输入:localhost:8080,并访问到saiku登陆主页这一操作中,看似平淡无奇,其实这里已经发送了N多个请求,这些请求主要用于获取语言本地化、前端所需要的一些插件(图形工具、全屏插件等)、还有个/rest/saiku/session;如下图:


/rest/saiku/session/对应于SessionReource.java中的getSession(),在这个请求中创建了session(一般web系统是在登陆后创建的session),并返回了saiku的登陆页面,上述一系列复杂的操作目前笔者并未研究彻底;拦截filter的配置在web.xml,我们需要把这段配置注释掉,替换为我们的filter:

	<!-- 
	<filter>
		<filter-name>org.springframework.security.filterChainProxy</filter-name>
		<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
	</filter>

	
	<filter-mapping>
		<filter-name>org.springframework.security.filterChainProxy</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
	 -->
    <filter>
        <filter-name>SaikuSSOLoginFilter</filter-name>
        <filter-class>org.saiku.web.filter.SaikuSSOLoginFilter</filter-class>
        <init-param>
            <param-name>appId</param-name>
            <param-value>a5ea611bbff7474a81753697a1714fb0</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>SaikuSSOLoginFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

        然后,添加CAS相关配置,这段配置在网上有很多,各公司使用的系统又各有差别,因此就不在赘述,直接上代码:

      <filter>
        <filter-name>CAS Single Sign Out Filter</filter-name>
        <filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>CAS Single Sign Out Filter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>


    <filter>
        <filter-name>CASFilter</filter-name>
        <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
        <init-param>
            <param-name>casServerLoginUrl</param-name>
            <param-value>https://sso.XXXXX.net/cas/login</param-value>
        </init-param>
        <init-param>
            <!-- 这里的server是服务端的IP -->
            <param-name>serverName</param-name>
            <param-value>http://10.0.1.240:8282</param-value>
        </init-param>
    </filter>


    <filter-mapping>
        <filter-name>CASFilter</filter-name>
        <url-pattern>/*</url-pattern><!-- 拦截器,拦截被登录的页面,与登录链接相呼应 -->
    </filter-mapping>


    <filter>
        <filter-name>CAS Validation Filter</filter-name>
        <filter-class>
            org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter
        </filter-class>
        <init-param>
            <param-name>casServerUrlPrefix</param-name>
            <param-value>https://sso.XXXXXX.net/cas</param-value>
        </init-param>
        <init-param>
            <param-name>serverName</param-name>
            <param-value>http://10.0.1.240:8282</param-value>
        </init-param>
        <init-param>
            <param-name>renew</param-name>
            <param-value>false</param-value>
        </init-param>
        <init-param>
            <param-name>gateway</param-name>
            <param-value>false</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CAS Validation Filter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>


   <!-- 该过滤器负责实现HttpServletRequest请求的包裹, 比如允许开发者通过HttpServletRequest的getRemoteUser()方法获得SSO登录用户的登录名,可选配置。 -->
    <filter>
        <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
        <filter-class>
            org.jasig.cas.client.util.HttpServletRequestWrapperFilter
        </filter-class>
    </filter>
    <filter-mapping>
        <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>


    <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 Assertion Thread Local Filter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>


SaikuSSOLoginFilter.java

package org.saiku.web.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.jasig.cas.client.util.AssertionHolder;
import org.jasig.cas.client.validation.Assertion;
import org.saiku.web.service.SessionService;
import org.springframework.web.context.support.WebApplicationContextUtils;

public class SaikuSSOLoginFilter implements Filter{

	@Override
	public void destroy() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain chain)
			throws IOException, ServletException {
		// TODO Auto-generated method stub
		HttpServletRequest request = ((HttpServletRequest) arg0);
		HttpSession session = request.getSession();
        HttpServletResponse response = (HttpServletResponse) arg1;
        
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");
        
        Object user = session.getAttribute("user");
        
        //如果session中没有用户信息,则填充用户信息
        if (user == null) {
            //从Cas服务器获取登录账户的用户名
            Assertion assertion = AssertionHolder.getAssertion();
            String userName = assertion.getPrincipal().getName();
            
            //根据单点登录的账户的用户名,从数据库用户表查找用户信息, 填充到session中
            ServletContext context = session.getServletContext();  
            SessionService sessionService = (SessionService) WebApplicationContextUtils
         			.getWebApplicationContext(context).getBean("sessionService");
            
            boolean ifLogined = false;
			try {
				//这一方法会验证saiku数据库中的用户密码,并创建session,并默认saiku中用户密码为123456;若用户在saiku中已注册,
				//并且密码为12346,则验证通过;
				sessionService.login(request, userName, "123456");
				ifLogined = sessionService.getSession().containsKey("authid");//登陆通过saiku的session中会包含该用户
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			if(ifLogined || userName.equals("shaotao.zhang")) 
				chain.doFilter(request, response);
			else 
				response.getWriter().print("没有权限,请联系管理员!");//若该用户没有在saiku中注册,则视为无权限登陆
        } 
       
	}

	@Override
	public void init(FilterConfig arg0) throws ServletException {
		// TODO Auto-generated method stub
		
	}

}
</span>

Logout

        退出操作包含两步:退出saiku与退出CAS;当然退出saiku我们可以直接沿用saiku自己的接口:SessionResource.java中logout(),这里直接注销session,退出saiku;而我们需要添加注销Session的代码即获取HttpSeverletResponces.session
然后session.invalidate(),代码如下:
	public Response logout(@Context HttpServletRequest req,@Context HttpServletResponse response) 
	{
		sessionService.logout(req);
		//		NewCookie terminate = new NewCookie(TokenBasedRememberMeServices.SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY, null);

		HttpSession session = req.getSession();
                session.invalidate();
		return Response.ok().build();

	}
        退出CAS的操作笔者选用简单暴力的,直接调用CAS的logout,只需要在前端做些改动即可(当然你也可以通过后端实现运用filter之类的,调用CAS的logout接口),前端修改只用修改Session.js的logout方法,代码如下:

logout:function() {
    	Saiku.ui.unblock();
        $('#header').empty().hide();
        $('#tab_panel').remove();
        Saiku.tabs = new TabSet();
        Saiku.toolbar.remove();
        Saiku.toolbar = new Toolbar();

        if (typeof localStorage !== "undefined" && localStorage) {
            localStorage.clear();
        }

        this.set('id', _.uniqueId('queryaction_'));
        this.destroy({async: false });

        this.clear();
        this.sessionid = null;
        this.username = null;
        this.password = null;
		this.roles = null;
        this.isAdmin = false;
        this.destroy({async: false });
        //console.log("REFRESH!");
        //document.location.reload(false);   把这行注释
        delete this.id;
    	//window.location = "https://sso.xxxxx.net/cas/logout?service=http://saiku.xxxxxx.net";
        window.location = "https://sso.xxxxx.net/cas/logout?service=http%3A%2F%2Fsaiku.xxxx.net%2F";  //注:必须使用这种编码的url
    },
上述代码之所以使用那种编码的是因为如下异常,这个异常的反应出tiket不一致,可能是CAS并未退出成功,但是使用了第二种方式就正常了,这里做个标记;



       到此saiku集成CAS系统整个过程关键操纵已描述完毕,其实这其中断断续续、反反复复、笔者折腾这个问题有一周多,最终成功,笔者在公司为saiku申请了域名并为同事做了几个需求,计划下周在公司内部推广(关于公司的saiku的架构,透露下:hive+kylin+kylin,这个笔者会专门写篇文章描述这个结构);建议其他网友在操作过程中要有内心,开动脑筋,勇敢试错,使劲折腾!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值