Saiku调用WS接口

关于saiku集成系统单点登录告一段落,始终没想好怎么去做,主要是因为saiku有自己的权限定义,一直没想好关于saiku本身的权限信息以及用户信息怎么处理(在这里笔者希望已实现saiku单点登录的大佬不吝赐教,感激~)

这里实现了在saiku源码里面调用公司内部的WS接口来验证登录时的密码信息(因为saiku本身未使用dubbo,所以无法直接通过maven引入dubbo包去调用接口)

如果已查看了saiku登录源码追踪(十三)我们就已经大概知道saiku登录时代码执行过程啦,接下来我们就来更改这里的密码校验,调用其他组件的WS接口验证登录

>>调用WS接口

1.在saiku-webapp项目下 找到 WEB-INF/applicationContext-spring-security-jdbc.xml 文件

作出以下更改,替换原来的bean信息,将原来的 org.springframework.security.authentication.dao.DaoAuthenticationProvider 类 替换为自己定义的 org.saiku.service.util.security.authentication.UmServiceProvider 类

 <!--
  <bean id="daoAuthenticationProvider"
class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
<property name="userDetailsService">
<ref bean="userDetailsService" />
</property>
<property name="passwordEncoder">
<ref bean="passwordEncoder" />
</property>
</bean>
-->
<bean id="daoAuthenticationProvider"
class="org.saiku.service.util.security.authentication.UmServiceProvider">
<property name="userDetailsService">
<ref bean="userDetailsService" />
</property>
<property name="passwordEncoder">
<ref bean="passwordEncoder" />
</property>
</bean>

 

2.org.saiku.service.util.security.authentication.UmServiceProvider 类定义在saiku-service项目下的 对应包(org.saiku.service.util.security.authentication.)路径下

内容如下:(内容上基本语原来的DaoAuthenticationProvider 保持一致,更改密码校验方法:additionalAuthenticationChecks(UserDetails userDetails,UsernamePasswordAuthenticationToken authentication))

思路: 注释掉源代码中的密码校验方法passwordEncoder.isPasswordValid

    新增自己的密码校验方法: validatePassword(UserDetails userDetails,UsernamePasswordAuthenticationToken authentication,Object salt)

/*密码校验思路:
1.先判断密码是不是固定密码值,从properties文件中获取的自定义密码信息(我这里是因为嵌入系统时有用到固定密码对应用户以及角色信息气分享saiku数据信息所以才有,如果不需要可以去掉第一个if中的判断 fixedPassword)   
2.再判断密码是否满足 WS接口(WS是公司自定义的相关接口信息,通过jar包引入saiku去调用的,下面会做出相应解析)    
3.以上两种都不符合时,调用saiku自己的密码校验,如果失败就校验失败了。(以上任意一种校验方式成功都会成功登录哦)
*/

UmServiceProvider.java

package org.saiku.service.util.security.authentication;

import org.saiku.service.util.GetFixedPasswordUtil;
import org.saiku.service.util.UMLoginWSUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider;
import org.springframework.security.authentication.dao.SaltSource;
import org.springframework.security.authentication.encoding.PasswordEncoder;
import org.springframework.security.authentication.encoding.PlaintextPasswordEncoder;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.util.Assert; import com.imodule.ws.soa.um.result.xsd.UmLoginResult; import clover.org.apache.commons.lang.StringUtils; public class UmServiceProvider extends AbstractUserDetailsAuthenticationProvider {
// ~ Static fields/initializers
// ===================================================================================== /**
* The plaintext password used to perform
* {@link PasswordEncoder#isPasswordValid(String, String, Object)} on when the user is
* not found to avoid SEC-2056.
*/
private static final String USER_NOT_FOUND_PASSWORD = "userNotFoundPassword"; // ~ Instance fields
// ================================================================================================ private PasswordEncoder passwordEncoder; /**
* The password used to perform
* {@link PasswordEncoder#isPasswordValid(String, String, Object)} on when the user is
* not found to avoid SEC-2056. This is necessary, because some
* {@link PasswordEncoder} implementations will short circuit if the password is not
* in a valid format.
*/
private String userNotFoundEncodedPassword; private SaltSource saltSource; private UserDetailsService userDetailsService; private GetFixedPasswordUtil getFixedPasswordUtil; public UmServiceProvider() {
setPasswordEncoder(new PlaintextPasswordEncoder());
} // ~ Methods
// ========================================================================================================
/*密码校验思路: 1.先判断密码是不是固定密码值,从properties文件中获取的自定义密码信息(我这里是因为嵌入系统时有用到固定密码对应用户以及角色信息气分享saiku数据信息所以才有,如果不需要可以去掉第一个if中的判断 fixedPassword)
  2.再判断密码是否满足 WS接口(WS是公司自定义的相关接口信息,通过jar包引入saiku去调用的,下面会做出相应解析)
3.以上两种都不符合时,调用saiku自己的密码校验,如果失败就校验失败了。(以上任意一种校验方式成功都会成功登录哦)
*/
private void validatePassword(UserDetails userDetails,UsernamePasswordAuthenticationToken authentication,Object salt){
getFixedPasswordUtil = new GetFixedPasswordUtil();
UMLoginWSUtil umloginWS = new UMLoginWSUtil(); String presentedPassword = authentication.getCredentials().toString(); // get user input password
String fixedPassword = getFixedPasswordUtil.getSaikuUserPassword();
if(StringUtils.isNotBlank(fixedPassword) && fixedPassword.equals(presentedPassword)){
logger.debug("Authentication successs: password match fixed value which store in properties file.");
}else {
//authentication.getName(): user input userid
UmLoginResult umloginResult = umloginWS.getUmLoginWS(authentication.getName(), presentedPassword);
//successs: umloginResult.getResultStatus()=0, fail:umloginResult.getResultStatus()=2
if(umloginResult.getResultStatus().equals("0")){// successs
logger.debug("Authentication success: password match stored value in um Database");
}else{
// if not match properties and um system,use saiku self validator to validate password.
if (!passwordEncoder.isPasswordValid(userDetails.getPassword(),
presentedPassword, salt)) {
logger.debug("Authentication failed: password does not match stored value(neither in properteis nor um system or saiku db.)");
throw new BadCredentialsException(messages.getMessage(
"AbstractUserDetailsAuthenticationProvider.badCredentials",
"Bad credentials"));
}
}
}
} @SuppressWarnings("deprecation")
protected void additionalAuthenticationChecks(UserDetails userDetails,
UsernamePasswordAuthenticationToken authentication)
throws AuthenticationException {
Object salt = null; if (this.saltSource != null) {
salt = this.saltSource.getSalt(userDetails);
} if (authentication.getCredentials() == null) {
logger.debug("Authentication failed: no credentials provided"); throw new BadCredentialsException(messages.getMessage(
"AbstractUserDetailsAuthenticationProvider.badCredentials",
"Bad credentials"));
} validatePassword(userDetails,authentication,salt); /*if (!passwordEncoder.isPasswordValid(userDetails.getPassword(),
presentedPassword, salt)) {
logger.debug("Authentication failed: password does not match stored value"); throw new BadCredentialsException(messages.getMessage(
"AbstractUserDetailsAuthenticationProvider.badCredentials",
"Bad credentials"));
}*/
} protected void doAfterPropertiesSet() throws Exception {
Assert.notNull(this.userDetailsService, "A UserDetailsService must be set");
} protected final UserDetails retrieveUser(String username,
UsernamePasswordAuthenticationToken authentication)
throws AuthenticationException {
UserDetails loadedUser; try {
loadedUser = this.getUserDetailsService().loadUserByUsername(username);
}
catch (UsernameNotFoundException notFound) {
if (authentication.getCredentials() != null) {
String presentedPassword = authentication.getCredentials().toString();
passwordEncoder.isPasswordValid(userNotFoundEncodedPassword,
presentedPassword, null);
}
throw notFound;
}
catch (Exception repositoryProblem) {
throw new InternalAuthenticationServiceException(
repositoryProblem.getMessage(), repositoryProblem);
} if (loadedUser == null) {
throw new InternalAuthenticationServiceException(
"UserDetailsService returned null, which is an interface contract violation");
}
return loadedUser;
} /**
* Sets the PasswordEncoder instance to be used to encode and validate passwords. If
* not set, the password will be compared as plain text.
* <p>
* For systems which are already using salted password which are encoded with a
* previous release, the encoder should be of type
* {@code org.springframework.security.authentication.encoding.PasswordEncoder}.
* Otherwise, the recommended approach is to use
* {@code org.springframework.security.crypto.password.PasswordEncoder}.
*
* @param passwordEncoder must be an instance of one of the {@code PasswordEncoder}
* types.
*/
public void setPasswordEncoder(Object passwordEncoder) {
Assert.notNull(passwordEncoder, "passwordEncoder cannot be null"); if (passwordEncoder instanceof PasswordEncoder) {
setPasswordEncoder((PasswordEncoder) passwordEncoder);
return;
} if (passwordEncoder instanceof org.springframework.security.crypto.password.PasswordEncoder) {
final org.springframework.security.crypto.password.PasswordEncoder delegate = (org.springframework.security.crypto.password.PasswordEncoder) passwordEncoder;
setPasswordEncoder(new PasswordEncoder() {
public String encodePassword(String rawPass, Object salt) {
checkSalt(salt);
return delegate.encode(rawPass);
} public boolean isPasswordValid(String encPass, String rawPass, Object salt) {
checkSalt(salt);
return delegate.matches(rawPass, encPass);
} private void checkSalt(Object salt) {
Assert.isNull(salt,
"Salt value must be null when used with crypto module PasswordEncoder");
}
}); return;
} throw new IllegalArgumentException(
"passwordEncoder must be a PasswordEncoder instance");
} private void setPasswordEncoder(PasswordEncoder passwordEncoder) {
Assert.notNull(passwordEncoder, "passwordEncoder cannot be null"); this.userNotFoundEncodedPassword = passwordEncoder.encodePassword(
USER_NOT_FOUND_PASSWORD, null);
this.passwordEncoder = passwordEncoder;
} protected PasswordEncoder getPasswordEncoder() {
return passwordEncoder;
} /**
* The source of salts to use when decoding passwords. <code>null</code> is a valid
* value, meaning the <code>DaoAuthenticationProvider</code> will present
* <code>null</code> to the relevant <code>PasswordEncoder</code>.
* <p>
* Instead, it is recommended that you use an encoder which uses a random salt and
* combines it with the password field. This is the default approach taken in the
* {@code org.springframework.security.crypto.password} package.
*
* @param saltSource to use when attempting to decode passwords via the
* <code>PasswordEncoder</code>
*/
public void setSaltSource(SaltSource saltSource) {
this.saltSource = saltSource;
} protected SaltSource getSaltSource() {
return saltSource;
} public void setUserDetailsService(UserDetailsService userDetailsService) {
this.userDetailsService = userDetailsService;
} protected UserDetailsService getUserDetailsService() {
return userDetailsService;
}
}

3.关于从配置文件中读取固定密码信息。 saikuUser.properties中读取 fixedPassword

在saiku-service中新建Util类:  /saiku-service/src/main/java/org/saiku/service/util/GetFixedPasswordUtil.java

package org.saiku.service.util;

import java.io.FileInputStream;
import java.io.InputStream;
import java.rmi.RemoteException;
import java.util.Properties; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import com.imodule.ws.soa.um.UmSoaPortTypeProxy;
import com.imodule.ws.soa.um.result.xsd.UmLoginResult; /**
* Get password from properties file,for validate password.
* ps: properties file path keep on with this Class path .
* @author S0111
*
*/
public class GetFixedPasswordUtil { private String SAIKU_USER_PASSWORD = "saikuUserPassword";
private String FILE_NAME = "saikuUser.properties";
// FileInputStream in = null;
InputStream ins = null;
String saikuUserPassword = null;
protected final Log logger = LogFactory.getLog(getClass()); /**
* Get local password from properties file.
* @return
*/
public String getSaikuUserPassword(){
try{
Properties properties = new Properties();
// ins = new FileInputStream(this.getClass().getResource("/").getPath()+FILE_NAME);
// ins = getClass().getResourceAsStream(FILE_NAME);
ins = GetFixedPasswordUtil.class.getClassLoader().getResourceAsStream(FILE_NAME);
properties.load(ins);
saikuUserPassword = properties.getProperty(SAIKU_USER_PASSWORD);
logger.debug("GetFixedPasswordUtil - getSaikuUserPassword ,read the properties file,password value is:"+saikuUserPassword);
}catch(Exception e){
logger.debug("GetFixedPasswordUtil - getSaikuUserPassword failed, Caused by:"+e);
e.printStackTrace();
}finally{
if(ins != null){
try{
ins.close();
}catch(Exception e){
logger.debug("GetFixedPasswordUtil - getSaikuUserPassword failed, Caused by:"+e);
e.printStackTrace();
}
}
}
return saikuUserPassword; } }

  

相应的在 saiku-service项目中的 src/main/resources目录下新建properties文件: /saiku-service/src/main/resources/saikuUser.properties  (这里表示不管啥用户只有是saiku有的用户,使用密码saiku123都能登录saiku)

saikuUserPassword=saiku123

 

4.关于saiku源码中调用其他WS接口的Util类:/saiku-service/src/main/java/org/saiku/service/util/UMLoginWSUtil.java  

package org.saiku.service.util;

import java.rmi.RemoteException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import com.imodule.ws.soa.um.UmSoaPortTypeProxy;
import com.imodule.ws.soa.um.result.xsd.UmLoginResult;
/**
* Use UM system login interface to validate userid and password
* @author S0111
*
*/
public class UMLoginWSUtil { protected final Log logger = LogFactory.getLog(getClass()); public UmLoginResult getUmLoginWS(String username ,String password){
UmSoaPortTypeProxy um = new UmSoaPortTypeProxy();
UmLoginResult result = null;
try {
result = um.umLogin(username, password);
logger.debug("UMLoginWSUtil - getUmLoginWS,validate userid and password by UM interface success !!!");
} catch (RemoteException e) {
logger.debug("UMLoginWSUtil - getUmLoginWS,validate userid and password by UM interface failed !!!,Caused by:"+e);
e.printStackTrace();
}
return result;
}
}

  

 

5.关于调用其他WS接口验证

首先需要得到WS接口地址信息: http://11.22.33.44:8080/demo-ws/services/demo-soa?wsdl     #这只是个示例地址,每个公司提供的接口地址都不同

验证地址: 在浏览器中输入  http://11.22.33.44:8080/demo-ws/services/demo-soa?wsdl 去访问,正确的WS接口信息会返回 <wsdl:definitions xmlns:wsd ... 等类似信息

使用Eclipse新建Maven项目 saiku-um-ws  (项目命名随自己啦嘻嘻)

右击新建的羡慕 saiku-um-ws  -->  new   --> others  --> 选中下图中的 Web Service Client --> 点击 next

进入如下页面,在Service definition 处输入WS接口地址信息:http://11.22.33.44:8080/demo-ws/services/demo-soa?wsdl   然后点击finish 即可

再进去看就会看到新建的maven项目 saiku-um-ws已经被填充好了

pom.xml中内容如下:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <groupId>com.saiku.ws</groupId>
<artifactId>saiku-um-ws</artifactId>
<version>1.0</version>
<packaging>jar</packaging> <name>saiku-um-ws</name>
<url>http://maven.apache.org</url> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties> <dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.axis</groupId>
<artifactId>axis</artifactId>
<version>1.4</version>
</dependency> <dependency>
<groupId>javax.xml</groupId>
<artifactId>jaxrpc-api</artifactId>
<version>1.1</version>
</dependency> <dependency>
<groupId>commons-discovery</groupId>
<artifactId>commons-discovery</artifactId>
<version>0.2</version>
</dependency> <dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
</dependency> <dependency>
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
<version>1.4.01</version>
</dependency> <dependency>
<groupId>wsdl4j</groupId>
<artifactId>wsdl4j</artifactId>
<version>1.5.1</version>
</dependency> <dependency>
<groupId>soap</groupId>
<artifactId>soap</artifactId>
<version>2.3</version>
</dependency>
</dependencies>
</project>

  

将saiku-um-ws项目打包:  mvn  clean  install

再将saiku-um-ws相关的依赖引入 saiku-service项目中的 pom.xml即可

  <!-- add in  2019-03-11,for validate password use other system -->
<dependency>
<groupId>com.saiku.ws</groupId>
<artifactId>saiku-um-ws</artifactId>
<version>0.0.1-SNA</version>
</dependency> <dependency>
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
<version>1.4.01</version>
</dependency>

  

最后,重新编译整个saiku项目, mvn clean install 

获取saiku-server下的 target/dist/saiku-server  双击脚本saiku-start.bat 文件 启动saiku就可以啦~~~~~~~~~

  

======================二次更新 关于ws接口打包后的使用 start  20190627==============================

public class TestLogin {

	public static void main(String[] args) {
UmSoaPortTypeProxy um = new UmSoaPortTypeProxy();
UmLoginResult result = null;
try {
result = um.umLogin("test", "111");
System.out.println(result.getResultStatus());
System.out.println(result.getResultStatus().equals("0"));
result = um.umLogin("test", "123");
System.out.println(result.getResultStatus());
System.out.println(result.getResultStatus()=="0");
// logger.debug("UMLoginWSUtil - getUmLoginWS,validate userid and password by UM interface success !!!");
} catch (RemoteException e) {
// logger.debug("UMLoginWSUtil - getUmLoginWS,validate userid and password by UM interface failed !!!,Caused by:"+e);
e.printStackTrace();
}
System.out.println("result:"+result); } }

  

======================二次更新 关于ws接口打包后的使用 end 20190627==============================

Saiku调用WS接口(十四)的更多相关文章

  1. spring boot / cloud (十四) 微服务间远程服务调用的认证和鉴权的思考和设计,以及restFul风格的url匹配拦截方法

    spring boot / cloud (十四) 微服务间远程服务调用的认证和鉴权的思考和设计,以及restFul风格的url匹配拦截方法 前言 本篇接着<spring boot / cloud ...

  2. Atitit 图像处理之编程之类库调用的接口api cli gui ws rest  attilax大总结.docx

    Atitit 图像处理之编程之类库调用的接口api cli gui ws rest  attilax大总结.docx 1. 为什么需要接口调用??1 1.1. 为了方便集成复用模块类库1 1.2. 嫁 ...

  3. 详解C#泛型(二) 获取C#中方法的执行时间及其代码注入 详解C#泛型(一) 详解C#委托和事件(二) 详解C#特性和反射(四) 记一次.net core调用SOAP接口遇到的问题 C# WebRequest.Create 锚点“#”字符问题 根据内容来产生一个二维码

    详解C#泛型(二)   一.自定义泛型方法(Generic Method),将类型参数用作参数列表或返回值的类型: void MyFunc<T>() //声明具有一个类型参数的泛型方法 { ...

  4. “全栈2019”Java第八十四章:接口中嵌套接口详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  5. “全栈2019”Java第六十四章:接口与静态方法详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  6. [Effective Java 读书笔记] 第三章类和接口 第十三 -- 十四条

    第十三条 使类和成员的可访问性最小化 总得来说,我们应该尽量将成员的访问范围限制到最小!有利于解耦,开发.测试和优化都能够更加独立. 对于成员(域,方法,嵌套类和嵌套接口),有四种可能的访问级别,访问 ...

  7. Chrome浏览器扩展开发系列之十四

    Chrome浏览器扩展开发系列之十四:本地消息机制Native messaging 时间:2015-10-08 16:17:59      阅读:1361      评论:0      收藏:0    ...

  8. javaSE第二十四天

    第二十四天    363 1:多线程(理解)    363 (1)JDK5以后的Lock锁    363 A:定义    363 B:方法:    364 C:具体应用(以售票程序为例)    364 ...

  9. How Tomcat Works(十四)补充

    在How Tomcat Works(十四)中,本人并没有对javax.servlet.Filter及javax.servlet.FilterChain做详细的描述,本文在这里做一下补充 FilterC ...

随机推荐

  1. ATM Mechine (概率DP)

    题意:去银行取最多K钱,想要全部取完,但是有个限制就是如果你输入取钱的额度超过了你已有的钱,那么会接受一次警告并无法取钱,然后求最多不超过w次警告的前提下你取完所有钱所需要的最少次数. 思路:概率DP ...

  2. 用java生成32位全球唯一的id编号

    GUID是一个128位长的数字,一般用16进制表示.算法的核心思想是结合机器的网卡.当地时间.一个随即数来生成GUID.从理论上讲,如果一台机器每秒产生10000000个GUID,则可以保证(概率意义 ...

  3. 基于ABP模块组件与依赖注入组件的项目插件开发

    注意,阅读本文,需要先阅读以下两篇文章,并且对依赖注入有一定的基础. 模块系统:http://www.cnblogs.com/mienreal/p/4537522.html 依赖注入:http://w ...

  4. app埋点

    目前APP埋点的主流有两种方式: 第一类是预先设定好想要获取的目标数据,让程序员撰写代码把“采集器”埋到相应的页面上,用于追踪和记录的用户的行为,并把实时数据传送到后台数据库或者客户端. 第二类方法是 ...

  5. javascript监听按键

    document.addEventListener('keydown',test); function test(e){ var x=e.keyCode; if(x == 49){ console.l ...

  6. openvino program

    为了兼容 fpgaconf -b 00 -d 04 -f 1 xxx.bin 重新实现 #!/bin/bash B=${} D=${} F=${} BDF=${B##0x}:${D##0x}.${F# ...

  7. redhat6.4提权Ⅱ

    本次演示只针对redhat6.4, 其他的系统不知道有没有效果. 下面开始吧 建立普通用户并授予密码 [root@localhost yum.repos.d]# useradd test [root@ ...

  8. 使用VS Code调试Node

    1.双击打开vscode 2.找到底层面板 把ctrl改成LF 2. 3.打开文件夹,建立项目test 4.新建hellow.js 输入: var name='world'; var s='hello ...

  9. 由 UWP 版网易云音乐闪退引发的博文

    今天,不知怎么的.网易云音乐出现了一打开就闪退的情况.百度了好些时候未果,就直接 Windows + i 打开 Windows 设置 > 应用 在应用和功能列表中找到网易云音乐,在展开的 高级选 ...

  10. 解决github访问及上传慢的问题

    在本地host文件中添加映射 http://tool.chinaz.com/dns , 查询 github.global.ssl.fastly.net 和 assets-cdn.github.com ...