Saiku登录源码追踪.(十三)
Saiku登录源码追踪呀~
>>首先我们需要debug跟踪saiku登录执行的源码信息
saiku源码的debug方式上一篇博客已有说明,这里简单介绍一下
在saiku启动脚本中添加如下命令: (windows下: start-saiku.bat)
set CATALINA_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=n (后面可能还会有一些JVM参数信息)
使用Eclipse打开saiku源码 -- > Eclipse工具栏中的 Run --> Debug configurations --> Remote Java Application --> 选中对应的源码项目(saiku-web),远程访问saiku的ip,以及脚本中指定监听的端口 (address) 8787 --> Debug
在浏览器中根据saiku地址信息访问saiku,输入用户名以及密码信息登录,Eclipse则会进入对应的debug阶段。
>>源码追踪
1.首先会调用 saiku-web项目 org.saiku.web.rest.resources 包下的 SessionResource中的登录方法
sessionService.login(res,username,password)
/**
* Saiku Session Endpoints
*/
@Component
@Path("/saiku/session")
public class SessionResource { /*此处省略其他代码信息*/ private ISessionService sessionService; /**
* Login to Saiku
* @summary Login
* @param req Servlet request
* @param username Username
* @param password Password
* @return A 200 response
*/
@POST
@Consumes("application/x-www-form-urlencoded")
public Response login(
@Context HttpServletRequest req,
@FormParam("username") String username,
@FormParam("password") String password)
{
try {
sessionService.login(req, username, password);
return Response.ok().build();
}
catch (Exception e) {
log.debug("Error logging in:" + username, e);
return Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getLocalizedMessage()).build();
}
}
}
2.进入org.saiku.web.service 包下的 SessionService类中的 sessionService.login(res,username,password)方法
进行认证的方法主要是: authenticate(req, username, password);
package org.saiku.web.service;
/*此处省略了导入相关包信息*/
public class SessionService implements ISessionService { /**此处省略其他代码*/ /* (non-Javadoc)
* @see org.saiku.web.service.ISessionService#login(javax.servlet.http.HttpServletRequest, java.lang.String, java.lang.String)
*/
public Map<String, Object> login(HttpServletRequest req, String username, String password ) throws LicenseException {
Object sl = null;
String notice = null;
HttpSession session = ((HttpServletRequest)req).getSession(true);
session.getId();
sessionRepo.setSession(session);
try {
sl = l.getLicense();
} catch (Exception e) {
log.debug("Could not process license", e);
throw new LicenseException("Error fetching license. Get a free license from http://licensing.meteorite.bi. You can upload it at /upload.html");
} if (sl != null) { try {
l.validateLicense();
} catch (RepositoryException | IOException | ClassNotFoundException e) {
log.debug("Repository Exception, couldn't get license", e);
throw new LicenseException("Error fetching license. Please check your logs.");
} try {
if (l.getLicense() instanceof SaikuLicense2) { if (authenticationManager != null) {
authenticate(req, username, password);
}
if (SecurityContextHolder.getContext() != null
&& SecurityContextHolder.getContext().getAuthentication() != null) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication(); if (authorisationPredicate.isAuthorised(auth)) {
Object p = auth.getPrincipal();
createSession(auth, username, password);
return sessionHolder.get(p);
} else {
log.info(username + " failed authorisation. Rejecting login");
throw new RuntimeException("Authorisation failed for: " + username);
}
}
return new HashMap<>();
}
} catch (IOException | ClassNotFoundException | RepositoryException e) {
log.debug("Repository Exception, couldn't get license", e);
throw new LicenseException("Error fetching license. Please check your logs.");
}
}
return null;
}
}
3.继续进入SessionService的 authenticate (req,username,password)方法进行认证
主要认证: Authentication authentication = this.authenticationManager.authenticate(token);
/* (non-Javadoc)
* @see org.saiku.web.service.ISessionService#authenticate(javax.servlet.http.HttpServletRequest, java.lang.String, java.lang.String)
*/
public void authenticate(HttpServletRequest req, String username, String password) {
try {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password);
token.setDetails(new WebAuthenticationDetails(req));
Authentication authentication = this.authenticationManager.authenticate(token);
log.debug("Logging in with [{}]", authentication.getPrincipal());
SecurityContextHolder.getContext().setAuthentication(authentication);
}
catch (BadCredentialsException bd) {
throw new RuntimeException("Authentication failed for: " + username, bd);
} }
4.转入spring-security认证框架中的 org.springframework.security.authentication包下的ProviderManager类中的 this.authenticationManager.authenticate(token)方法
主要认证: result = provider.authenticate(authentication);
/**
* Attempts to authenticate the passed {@link Authentication} object.
* <p>
* The list of {@link AuthenticationProvider}s will be successively tried until an
* <code>AuthenticationProvider</code> indicates it is capable of authenticating the
* type of <code>Authentication</code> object passed. Authentication will then be
* attempted with that <code>AuthenticationProvider</code>.
* <p>
* If more than one <code>AuthenticationProvider</code> supports the passed
* <code>Authentication</code> object, only the first
* <code>AuthenticationProvider</code> tried will determine the result. No subsequent
* <code>AuthenticationProvider</code>s will be tried.
*
* @param authentication the authentication request object.
*
* @return a fully authenticated object including credentials.
*
* @throws AuthenticationException if authentication fails.
*/
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
Class<? extends Authentication> toTest = authentication.getClass();
AuthenticationException lastException = null;
Authentication result = null;
boolean debug = logger.isDebugEnabled(); for (AuthenticationProvider provider : getProviders()) {
if (!provider.supports(toTest)) {
continue;
} if (debug) {
logger.debug("Authentication attempt using "
+ provider.getClass().getName());
} try {
result = provider.authenticate(authentication); if (result != null) {
copyDetails(authentication, result);
break;
}
}
catch (AccountStatusException e) {
prepareException(e, authentication);
// SEC-546: Avoid polling additional providers if auth failure is due to
// invalid account status
throw e;
}
catch (InternalAuthenticationServiceException e) {
prepareException(e, authentication);
throw e;
}
catch (AuthenticationException e) {
lastException = e;
}
} if (result == null && parent != null) {
// Allow the parent to try.
try {
result = parent.authenticate(authentication);
}
catch (ProviderNotFoundException e) {
// ignore as we will throw below if no other exception occurred prior to
// calling parent and the parent
// may throw ProviderNotFound even though a provider in the child already
// handled the request
}
catch (AuthenticationException e) {
lastException = e;
}
} if (result != null) {
if (eraseCredentialsAfterAuthentication
&& (result instanceof CredentialsContainer)) {
// Authentication is complete. Remove credentials and other secret data
// from authentication
((CredentialsContainer) result).eraseCredentials();
} eventPublisher.publishAuthenticationSuccess(result);
return result;
} // Parent was null, or didn't authenticate (or throw an exception). if (lastException == null) {
lastException = new ProviderNotFoundException(messages.getMessage(
"ProviderManager.providerNotFound",
new Object[] { toTest.getName() },
"No AuthenticationProvider found for {0}"));
} prepareException(lastException, authentication); throw lastException;
}
5.转入 org.springframework.security.authentication.dao包下的 AbstractUserDetailsAuthenticationProvider类中的 result = provider.authenticate(authentication);
关于密码的校验主要是:additionalAuthenticationChecks(user,(UsernamePasswordAuthenticationToken) authentication);
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
Assert.isInstanceOf(UsernamePasswordAuthenticationToken.class, authentication,
messages.getMessage(
"AbstractUserDetailsAuthenticationProvider.onlySupports",
"Only UsernamePasswordAuthenticationToken is supported")); // Determine username
String username = (authentication.getPrincipal() == null) ? "NONE_PROVIDED"
: authentication.getName(); boolean cacheWasUsed = true;
UserDetails user = this.userCache.getUserFromCache(username); if (user == null) {
cacheWasUsed = false; try {
user = retrieveUser(username,
(UsernamePasswordAuthenticationToken) authentication);
}
catch (UsernameNotFoundException notFound) {
logger.debug("User '" + username + "' not found"); if (hideUserNotFoundExceptions) {
throw new BadCredentialsException(messages.getMessage(
"AbstractUserDetailsAuthenticationProvider.badCredentials",
"Bad credentials"));
}
else {
throw notFound;
}
} Assert.notNull(user,
"retrieveUser returned null - a violation of the interface contract");
} try {
preAuthenticationChecks.check(user);
additionalAuthenticationChecks(user,
(UsernamePasswordAuthenticationToken) authentication);
}
catch (AuthenticationException exception) {
if (cacheWasUsed) {
// There was a problem, so try again after checking
// we're using latest data (i.e. not from the cache)
cacheWasUsed = false;
user = retrieveUser(username,
(UsernamePasswordAuthenticationToken) authentication);
preAuthenticationChecks.check(user);
additionalAuthenticationChecks(user,
(UsernamePasswordAuthenticationToken) authentication);
}
else {
throw exception;
}
}
6.org.springframework.security.authentication.dao包下的 DaoAuthenticationProvider 类中 additionalAuthenticationChecks(user,(UsernamePasswordAuthenticationToken) authentication)方法如下
校验密码的主要方法: passwordEncoder.isPasswordValid(userDetails.getPassword(), presentedPassword,salt)
@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"));
}
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"));
}
}
好了,关于saiku登录源码就追踪到这里啦~ ,到这里我们就知道怎么更改saiku对密码校验的逻辑信息啦~
Saiku登录源码追踪.(十三)的更多相关文章
- saiku的源码包Bulid常见问题和jar包
最近在做kylin+mondrian+saiku的二次开发的时候,Bulid saiku的源码出现了很多问题,基本上一大部分问题jar找不到问题,很多jar国内网站都找不到.这时候只有手动下载然后注册 ...
- Yii2 使用 QQ 和 Weibo 第三方登录源码
我们社区在 yii2-authclient 多次升级后,登录异常.一直想寻求一种通用的方法,尽量不重写 OAuth2, BaseOAuth 以及 OAuthToken 类, 所以本次直接在 initU ...
- 源码追踪,解决Could not locate executable null\bin\winutils.exe in the Hadoop binaries.问题
在windows系统本地运行spark的wordcount程序,会出现一个异常,但不影响现有程序运行. >>提君博客原创 http://www.cnblogs.com/tijun/ & ...
- [大数据可视化]-saiku的源码包Bulid常见问题和jar包
最近在做kylin+mondrian+saiku的二次开发的时候,Bulid saiku的源码出现了很多问题,基本上一大部分问题jar找不到问题,很多jar国内网站都找不到.这时候只有手动下载然后注册 ...
- OpenJDK源码研究笔记(十三):Javac编译过程中的上下文容器(Context)、单例(Singleton)和延迟创建(LazyCreation)3种模式
在阅读Javac源码的过程中,发现一个上下文对象Context. 这个对象用来确保一次编译过程中的用到的类都只有一个实例,即实现我们经常提到的"单例模式". 今天,特意对这个上下文 ...
- CAS Server集成QQ登录、新浪微博登录源码及配置文件
转载自素文宅博客:https://blog.yoodb.com/yoodb/article/detail/1446 CAS Server集成QQ第三方登录,CAS Server集成新浪微博第三方登录以 ...
- Spring Boot 注解之ObjectProvider源码追踪
最近依旧在学习阅读Spring Boot的源代码,在此过程中涉及到很多在日常项目中比较少见的功能特性,对此深入研究一下,也挺有意思,这也是阅读源码的魅力之一.这里写成文章,分享给大家. 自动配置中的O ...
- [大数据可视化]-saiku的源码打包运行/二次开发构建
Saiku构建好之后,会将项目的各个模块达成jar包,整个项目也会打成war包 saiku目录结构: 我们选中saiku-server/target/ 下面的zip压缩包.这是个打包后的文件,进行 ...
- 类似818tu.co微信小说分销系统设计之多公众号网页授权自动登录源码
/** 转载请保留原地址以及版权声明,请勿恶意修改 * 作者:杨浩瑞 QQ:1420213383 独立博客:http://www.yxxrui.cn * [后台]http://xiaoshuo. ...
随机推荐
- 与图论的邂逅01:树的直径&基环树&单调队列
树的直径 定义:树中最远的两个节点之间的距离被称为树的直径. 怎么求呢?有两种官方的算法(不要问官方指谁我也不晓得): 1.两次搜索.首先任选一个点,从它开始搜索,找到离它最远的节点x.然后从x开始 ...
- 《linux就该这么学》第三节课 第二节命令笔记
命令笔记 (随笔原创,借鉴请修改) linux系统中一切都是文件 2.4 系统状态的命令: ifconfig : 查看系统网卡信息,包括网卡名称,ip地址,掩码,mac地址,收到数据包大 ...
- 3.Python3变量与基本数据类型
3.1保留字和标识符 3.1.1保留字 保留字是Python语言中已经被赋予特定意义的一些单词,开发程序时不可以把保留字作为变量.函数.类.模块和其他对象的名称来使用.保留字如下: 3.1.2标识符 ...
- GreenDao 使用和数据库升级
1使用方法 一.添加依赖 在bulid.gradle文件下的dependencies下添加所需依赖 compile 'org.greenrobot:greendao:3.2.2' // add l ...
- [openjudge-动态规划]鸣人的影分身
题目描述 描述 在火影忍者的世界里,令敌人捉摸不透是非常关键的.我们的主角漩涡鸣人所拥有的一个招数--多重影分身之术--就是一个很好的例子. 影分身是由鸣人身体的查克拉能量制造的,使用的查克拉越多,制 ...
- Java 五大原则
1.单一职责 不论是在设计类,接口还是方法,单一职责都会处处体现,单一职责的定义:我们把职责定义为系统变化的原因.所有在定义类,接口,方法的时候.定义完以后再去想一想是不能多于一个的动机去改变这个类, ...
- 使用日期插件用js处理日期格式
function compareDate(checkStartDate, checkEndDate) { var arys1= new Array(); var arys2= new Ar ...
- Html select、option、optgroup 标签
Html select 标签 </body> </html> <!-- select外部下拉选择框.name="xxx"标识后端获取名称 --> ...
- Docker Swarm nginx 集群搭建
环境1: 系统:Linux Centos 7.4 x64 内核:Linux docker 3.10.0-693.2.2.el7.x86_64 Docker 版本:18.09.1 redis 版本:ng ...
- opencv学习之路(28)、轮廓查找与绘制(七)——位置关系及轮廓匹配
一.点与轮廓的距离及位置关系 #include "opencv2/opencv.hpp" #include <iostream> using namespace std ...