ki4so 登录认证及凭证源码分析
ki4so 登录认证及凭证源码分析
hanzhankang 发表于4年前
ki4so 登录认证及凭证源码分析
  • 发表于 4年前
  • 阅读 700
  • 收藏 0
  • 点赞 0
  • 评论 0

新睿云服务器60天免费使用,快来体验!>>>   

此次以一个单次请求为开始,只研究服务器端对登录的处理过程,并未涉及客户端Server的处理过程。分析得比较啰嗦和杂乱,还请见谅。

Action 请求处理类:

@Controller

com.github.ebnew.ki4so.web.action.LoginAction 类定义:

@Controller

public class LoginAction {

 @Autowired

 protected CredentialResolver credentialResolver;

 @Autowired

 protected Ki4soService ki4soService;

 @Autowired

 protected LoginResultToView loginResultToView;

 /**

  * 登录接口,该接口处理所有与登录有关的请求。 包括以下几种情况: 1.

  * @param  model

  * @return

  */

 @RequestMapping("/login")

 public ModelAndView login(HttpServletRequest request,

   HttpServletResponse response) {

  ModelAndView mv = new ModelAndView("login");

  // 解析用户凭据。

  Credential credential = credentialResolver.resolveCredential(request);

  // 没有提供任何认证凭据。

  if (credential == null) {

   // 设置serivce地址到session中。

   String service = request

     .getParameter(WebConstants.SERVICE_PARAM_NAME);

   if (!StringUtils.isEmpty(service)) {

    request.getSession().setAttribute(

      WebConstants.KI4SO_SERVICE_KEY_IN_SESSION, service);

   }

   // 返回到登录页面,索取用户凭据。

   return mv;

  }

  // 提供了用户凭据

  else {

   // 调用核心结果进行凭据认证。

   LoginResult result = ki4soService.login(credential);

   // 将验证结果转换为视图输出结果。

   mv = loginResultToView.loginResultToView(mv, result, request,

     response);

  }

  return mv;

 }

// set method...

}

 spring-beans.xml 注入定义:

<!-- 组合凭据解析器对象 -->

 <bean id="credentialResolver" class="com.github.ebnew.ki4so.web.action.CompositeCredentialResolver">

  <property name="usernamePasswordCredentialResolver">

   <bean class="com.github.ebnew.ki4so.web.action.UsernamePasswordCredentialResolver"></bean>

  </property>

  <property name="encryCredentialResolver">

   <bean class="com.github.ebnew.ki4so.web.action.EncryCredentialResolver"></bean>

  </property>

 </bean>

 <!-- ki4so中心接口服务 -->

 <bean id="ki4soService" class="com.github.ebnew.ki4so.core.service.Ki4soServiceImpl" autowire="byName"></bean>

 <bean id="loginResultToView" class="com.github.ebnew.ki4so.web.action.DefaultLoginResultToView"></bean>

配置分析:

      这是Spring的典型配置注入方式,通过id可以定位到具体的实现类。

LoginAction 的处理流程:


用户调用login.do调用登录请求-->服务器端接受


服务器端接受后的处理:

-->解析用户凭证

  Credential credential = credentialResolver.resolveCredential(request); 

com.github.ebnew.ki4so.web.action.CompositeCredentialResolver 实现类的resolveCredential(request方法:

功能:

首先,从 http请求的cookie中解析出对应的加密后的凭据信息,如果cookie里没有,就从请求参数中获取(获取后,返回此值的加密信息,否则返回Null)

cookie和请求参数的键名:KI4SO_SERVER_EC

加密方式:



继续分析:加密凭证与非加密凭证:

if(request==null){

   return null;

  }

  Credential credential = null;

  if(encryCredentialResolver!=null){

   //先解析加密后的凭据。

   credential = encryCredentialResolver.resolveCredential(request);

  }

  //若返回空,则用原始凭据解析器解析。

  if(null == credential){

   if(usernamePasswordCredentialResolver!=null){

    credential = usernamePasswordCredentialResolver.resolveCredential(request);

   }

  }

………………

右边代码释义:

如果cookie里有值,就返回cookie里的值;如果没有,就从参数里获取,直接返回凭据对象:EncryCredential

cookie的键:"KI4SO_SERVER_EC"

EncryCredential凭据对象:返回的是一个凭据对象,有个构造方法,

EncryCredential实现了Credential的public boolean isOriginal();方法,此方法的解释是:

EncryCredential构建的对象直接是false

加密后的凭据:也就是说是cookie里的值,cookie里的值是经过加密的

encryCredentialResolver注入的类是:com.github.ebnew.ki4so.web.action.EncryCredentialResolver


如果没有加密凭据,就需要处理原始凭据:

usernamePasswordCredentialResolver的注入类:com.github.ebnew.ki4so.web.action.UsernamePasswordCredentialResolver

处理类的功能:从参数中解析出用户的用户名和密码信息(用户名和密码凭据解析器)。

         

此处理很简单,就是获取参数里的值,构造成:UsernamePasswordCredential,但此时,重写的public boolean isOriginal()方法的返回值就是true

==> 扩展及延伸:在这里可以扩展此类,实现“记住我”的功能,也就是设置cookie的超时时间


----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

以上的分析是针对com.github.ebnew.ki4so.web.action.LoginAction 类中的 public ModelAndView login 上半部分 解析用户凭据 的逻辑,如果用户凭证为空,就直接返回到登录界面;现在我们来分析当用户提供了登录凭据的实现流程:

也就是这一部分:

                        

这里代码看起来很简单,我们就来仔细分析分析。查找 ki4soService 的注入实现类,定位到:com.github.ebnew.ki4so.core.service.Ki4soServiceImpl,关于此类的结构见上图。

此类的相关属性的set注入都能在: spring-beans.xml  找到,我们现在先看login方法的实现:

代码中,最重要的是这段代码:
我们来继续看看authenticationManager注入的配置文件和实现类代码:


authenticate() 方法实现:



代码意思:循环调用所有的用户凭证解析器(配置里的),如果支持此用户凭证,调用:
循环处理完了,就判断是否找到了合适的认证处理器、是否认证通过;理想情况下是顺利进行,认证通过后,就继续下面的流程:解析用户凭据,解析用户凭据的注入配置:
代码分析:
authenticationHandlers 的定义:
也就是我们自己的验证模块:自定义查询用户名、密码进行匹配。 这个是Spring的List注入,说明这个list里有2个子类<bean>,2个类的实现与集成关系:


在上图中标注为*的AbstractUsernamePasswordAuthenticationHandler 抽象类中,实现了超类中的boolean supports(Credential credential);方法:




com.github.ebnew.ki4so.core.authentication.handlers.AbstractPreAndPostProcessingAuthenticationHandler 类实现了超类中的:boolean authenticate(Credential credential)  方法:

doAuthertication()的实现:

authenticateUsernamePasswordInternal() 方法是我们JeejenUsernamePasswordAuthenticationHandler里实现的数据库认证逻辑。


在上面的注入信息里都实现了:Principal resolvePrincipal(Credential credential) 方法

1.  com.github.ebnew.ki4so.core.authentication.resolvers.UsernamePasswordCredentialToPrincipalResolver 类的实现:

2.com.github.ebnew.ki4so.core.authentication.resolvers.EncryCredentialToPrincipalResolver类的实现:

通过循环调用所有的用户凭证解析器,看是否有合适的解析器、是否能解析出有效的用户凭证,如果成功了就返回此凭证(【如果是加密的凭证,就解密出来并生成凭证】)并跳出循环。如果一切都顺利的话,就:

authenticationPostHandler 的注入类是:com.github.ebnew.ki4so.core.authentication.DefaultAuthenticationPostHandler,方法postAuthentication(credential, principal)的实现为:

功能就是:构造验证结果对象并返回

至此,验证流程算是进行到一半了,返回了验证结果对象继续走:com.github.ebnew.ki4so.core.service.Ki4soServiceImpl 方法login()的下一个流程:






代码比较浅显易懂,核心也就是通过验证获得验证结果Authentication,如果验证中途出现异常,把异常类的状态code和msgKey封装成LoginResult返回给调用者处理就好了。

作为Action的LoginAction的具体login方法,负责处理登录结果对象LoginResult,做最终的页面呈现。



原文请见:http://note.youdao.com/share/?id=9dc8af987eeb19fa4c2af0bffb35b24a&type=note

  • 打赏
  • 点赞
  • 收藏
  • 分享
共有 人打赏支持
hanzhankang
粉丝 155
博文 161
码字总数 82578
×
hanzhankang
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: