博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
developercenter完全剔除webflow
阅读量:6001 次
发布时间:2019-06-20

本文共 45264 字,大约阅读时间需要 150 分钟。

hot3.png

问题记录

1、配置文件报错,却可以正常运行(cas的war包和maven overlay 配置已删除),一脸懵逼。。。

2、spring加载bean,id="warnCookieGenerator"时

实现不是:org.jasig.cas.web.support.CookieRetrievingCookieGenerator

而是:org.jasig.cas.web.WarningCookieRetrievingCookieGenerator

错误出现背景,比照cas中login-webflow.xml定义的流程改写为相应的controller和辅助类,

然后在在加载"warnCookieGenerator"实现时,class指定错误,使其识别不出HttpServletResponse实例,然后断言一直报错。

解决思路,比较将自己改造的流程和cas原始流程都debug一遍,比较相关类的实现是否一致。

3、将cas生成的tgt放入session中,下一次请求时,获取不到tgt属性。

原因可能是未修改的cas处理逻辑中,某一处将名为:“ticketGrantingTicketId“”的属性移除了。

暂时未找到移除位置或逻辑,将属性名改为“ticket”,问题解决。

 

改造过程

1、自定义认证实现

1.1、首先创建实现了AuthenticationHandler接口(其他AuthenticationHandler的实现类也可以)的类。

我继承了抽象类AbstractUsernamePasswordAuthenticationHandler,实现其中

authenticateUsernamePasswordInternal方法,就是根据前端用户提交的登陆信息,都数据中心查一下,用户是否合法(可调用dao层方法)。最后如何返回结果可以参考cas的实现方法:这里使用了

AcceptUsersAuthenticationHandler中的返回方式:

return createHandlerResult(saturnCredential, this.principalFactory.createPrincipal(accountName), null);

package com.saturn.account.ssoadapter;import com.saturn.account.domain.common.exception.SAccountInfoException;import com.saturn.account.domain.common.exception.SUnknowAccountException;import com.saturn.account.domain.manager.SAccountManager;import com.saturn.account.domain.model.SAccount;import com.saturn.account.ssoadapter.credential.SSaturnCredential;import org.apache.log4j.Logger;import org.jasig.cas.authentication.*;import org.jasig.cas.authentication.handler.support.AbstractUsernamePasswordAuthenticationHandler;import java.util.HashMap;import java.util.Map;import java.util.UUID;/** * \file       SCASAuthenticationHandler * \author     LiJiXiao * \date       2018/1/11 12:45 * \brief      CAS认证处理类 * \par Copyright (c): * Copyright (c) Saturn Team. All rights reserved. */public class SCASAuthenticationHandler extends AbstractUsernamePasswordAuthenticationHandler{   private static final Logger LOGGER = Logger.getLogger(SCASAuthenticationHandler.class);   /**    * 具体账户认证业务管理类引用    */   private SAccountManager accountManager = SAccountManager.getManager();   @Override   public HandlerResult authenticateUsernamePasswordInternal(UsernamePasswordCredential credential)         throws SUnknowAccountException   {      final SSaturnCredential saturnCredential = (SSaturnCredential) credential;      int authPlatform = saturnCredential.getPlatform();      // valid info      String accountName = saturnCredential.getUsername();      if (accountName == null || accountName.trim().equals(""))      {         LOGGER.error("accountNmae is null");         throw new SAccountInfoException("account info error");      }      String password = saturnCredential.getPassword();      if (password == null || password.trim().equals(""))      {         LOGGER.error("password is null");         throw new SAccountInfoException("account info error");      }      Map
token = new HashMap<>(); token.put("accountName", accountName); token.put("password", password); // uri暂时写死 token.put("uri", "db://127.0.0.1/no/com.saturn.account.domain.model.SAccount/"); // authenticate SAccount account = accountManager.authenticate(authPlatform, token); return createHandlerResult(saturnCredential, this.principalFactory.createPrincipal(accountName), null); }}    

1.2、修改配置引入自定义认证实现

在deployerConfigContext.xml中找到:

下添加bean: 

2、实现自定义登陆数据模型

2.1、新建实现了Credential接口(其它实现类也可以)的自定义数据类,我继承了

UsernamePasswordCredential

package com.saturn.account.ssoadapter.credential;import org.jasig.cas.authentication.UsernamePasswordCredential;import java.io.Serializable;/** * \file       SSaturnCredential * \author     LiJiXiao * \date       2018/1/11 11:10 * \brief      账户凭证 * \par Copyright (c): * Copyright (c) Saturn Team. All rights reserved. */public class SSaturnCredential extends UsernamePasswordCredential implements Serializable{   private static final long serialVersionUID = -1L;   /**    * 账户认证平台类别    */   private int platform;   /**    * 图形验证码    */   private String imageCode = "";   public SSaturnCredential()   {   }   public SSaturnCredential(int platform)   {      this.platform = platform;   }   @Override   public String toString()   {      return super.toString();   }   @Override   public boolean equals(Object object)   {      if (object == null)      {         return false;      }      if (object instanceof SSaturnCredential)      {         return false;      }      SSaturnCredential credential = (SSaturnCredential) object;      if (this.platform != credential.platform)      {         return false;      }      if (!imageCode.equals(credential.getImageCode()))      {         return false;      }      return super.equals(object);   }   @Override   public int hashCode()   {      int hash = super.hashCode() + this.platform;      hash += imageCode.hashCode();      return hash;   }   /**    * \name get/set    */   ///@{   public int getPlatform()   {      return platform;   }   public void setPlatform(int platform)   {      this.platform = platform;   }   public String getImageCode()   {      return imageCode;   }   public void setImageCode(String imageCode)   {      this.imageCode = imageCode;   }   ///@}}

2.2、因为本次使用cas不再使用spring-web-flow,所以不需修改:login-webflow.xml。只需要使用spring-mvc中的@requestBody等标签,直接接收Credential实例就好。

3、自定义返回用户信息

有两种方法,先了解小用户信息返回流程:

认证完之后,可以直接获取需要的账户信息,然后将账户信息放入handlerResult中的principle中,然后cas会一步步将principle放入authentication类中,我们可以从authentication中获取principle,然后返回前台。但是此过程中会有一个principleResolver参与,如果principleResolver是null,则将原来handlerResult中的principle给authentication,如果不为null,就解析一下在给authentication。cas默认的解析器是

PersonDirectoryPrincipalResolver类

此方法中判断解析器是否为空。

205428_f22a_3725601.png

此方法中拿到用户信息的map

210014_lsaL_3725601.png

具体是通过同类中的此方法获取

210047_1W5A_3725601.png

其中attributeRepository,是在spring中配置的实现。

因此自定义用户信息的两种方法:

第一:将信息直接放入result中的principle,然后将principleResolve设为null,但是还不知道如何设置为空,基础知识不好。。。

第二:自定义attributeRepository的实现类,重写getPerson方法,在此方法中将账户信息放进map,比如

<"account",account>,就好了。

4、将登陆流程翻译成controller,直接上码

登陆controller:

package com.saturn.controller;import com.saturn.account.domain.model.SAccount;import com.saturn.account.ssoadapter.credential.SSaturnCredential;import com.saturn.handler.sso.*;import com.saturn.model.SResult;import com.saturn.model.SResultCode;import org.jasig.cas.authentication.Credential;import org.jasig.cas.authentication.principal.Principal;import org.jasig.cas.authentication.principal.Service;import org.jasig.cas.services.UnauthorizedServiceException;import org.jasig.cas.web.support.WebUtils;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.binding.message.DefaultMessageContext;import org.springframework.binding.message.MessageContext;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.ResponseBody;import org.springframework.webflow.execution.Event;import org.springframework.webflow.execution.RequestContext;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;import java.util.Date;import java.util.Enumeration;import java.util.HashMap;import java.util.Map;/** * \file       SLoginController * \author     LiJiXiao * \date       2018/2/2 19:45 * \brief      L * \par Copyright (c): * Copyright (c) Saturn Team. All rights reserved. */@Controllerpublic class SLoginController{   private final transient Logger LOGGER = LoggerFactory.getLogger(this.getClass());   private final long EXPIRE_TIME = 60 * 1000;   @Autowired   SInitServletContextAndHttpServletRequestHandler initHandler;   @Autowired   STicketGrantingTicketCheckHandler TGTCheckHandler;   @Autowired   STerminateSessionHandler terminateSessionHandler;   @Autowired   SServiceAuthorizationCheckHandler serviceAuthorizationCheckHandler;   @Autowired   SGenerateServiceTicketHandler generateServiceTicketHandler;   @Autowired   SToAuthenticationHandler authenticationHandler;   @RequestMapping (value = "/validation/login", method = RequestMethod.GET)   @ResponseBody   public SResult validateLogin(HttpServletRequest request, HttpServletResponse response)   {      HttpSession session = request.getSession();      Service service = (Service) session.getAttribute("service");      initHandler.initServletContextAndHttpServletRequest(request, service);      Event TGTCheckEvent = TGTCheckHandler.ticketGrantingTicketCheck(request);      String TGTChecEventId = TGTCheckEvent.getId();      // TGT不存在      if ("notExists".equals(TGTChecEventId))      {         try         {            serviceAuthorizationCheckHandler.check(service, session);         }         catch (UnauthorizedServiceException e)         {            return SResult.failure(SResultCode.ACCESS_INVALID);         }         return SResult.failure(SResultCode.ACCOUNT_NOT_LOGIN, service);      }      // TGT无效      if ("invalid".equals(TGTChecEventId))      {         terminateSessionHandler.terminate(request, response);         try         {            serviceAuthorizationCheckHandler.check(service, session);         }         catch (UnauthorizedServiceException e)         {            return SResult.failure(SResultCode.ACCESS_INVALID);         }         // 去登陆         return SResult.failure(SResultCode.ACCOUNT_NOT_LOGIN);      }      // TGT有效      if ("valid".equals(TGTChecEventId))      {         if (service != null)         {            String renew = request.getParameter("renew");            if (!"".equals(renew) && null != renew)            {               try               {                  serviceAuthorizationCheckHandler.check(service, session);               }               catch (UnauthorizedServiceException e)               {                  return SResult.failure(SResultCode.ACCESS_INVALID);               }               // 去登陆               return SResult.failure(SResultCode.ACCOUNT_NOT_LOGIN);            }            else            {               Event generateServiceTicketEvent =                     generateServiceTicketHandler.generateServiceTicket(service, request);               if ("success".equals(generateServiceTicketEvent))               {                  Boolean warnCookieValue = (Boolean) session.getAttribute("warnCookieValue");                  if (warnCookieValue != null && warnCookieValue)                  {                     return SResult.success(SResultCode.SYSTEM_WARN);                  }                  String serviceTicketId = (String) request.getAttribute("serviceTicketId");                  if (serviceTicketId == null || "".equals(serviceTicketId))                  {                     return SResult.failure(SResultCode.ACCOUNT_NOT_LOGIN);                  }                  Map
responseInfo = new HashMap<>(); responseInfo.put("service", service.getId()); responseInfo.put("serviceTicketId", serviceTicketId); return SResult.success(responseInfo); // 回到 } if ("authenticationFailure".equals(generateServiceTicketEvent)) { return SResult.failure(SResultCode.ACCOUNT_NOT_LOGIN); } } } else { return SResult.success(SResultCode.ACCOUNT_LOGINED,session.getAttribute("account")); } } return SResult.failure(SResultCode.SYSTEM_ERROR); } @RequestMapping (value = "/real/login") @ResponseBody public SResult realLogin( HttpServletRequest request, HttpServletResponse response, @RequestBody SSaturnCredential credential) { HttpSession session = request.getSession(); boolean checkErrorTimesResult = checkErrorTimes(session); // 检查错误次数,小于5次正常登陆 if (checkErrorTimesResult) { MessageContext messageContext = new DefaultMessageContext(); Event event = authenticationHandler.submit(request, response, credential, messageContext); return responseByEvent(event, session); } else { // 大于等于5次需要验证图形验证码 boolean isNotExpire = isNotExpire(session); if (!isNotExpire) { return SResult.failure(SResultCode.VALID_CODE_EXPIRE); } boolean validImageCodeResult = validImageCode(session, credential); if (!validImageCodeResult) { return SResult.failure(SResultCode.VALID_CODE_ERROR); } // 验证码正取进行登陆验证 MessageContext messageContext = new DefaultMessageContext(); Event event = authenticationHandler.submit(request, response, credential, messageContext); return responseByEvent(event, session); } } // 错误时记录/添加错误次数 private void setErrorTimes(final HttpSession session) { int passwordErrorTimes = 0; if (session.getAttribute("errorTimes") != null) { passwordErrorTimes = (Integer) session.getAttribute("errorTimes"); passwordErrorTimes++; } else { session.setAttribute("errorTimes", passwordErrorTimes); } } private boolean checkErrorTimes(final HttpSession session) { Integer errorTimes = (Integer) session.getAttribute("errorTimes"); if (errorTimes != null) { return errorTimes < 5; } return true; } private boolean isNotExpire(final HttpSession session) { Date now = new Date(); Date createTime = (Date) session.getAttribute("createTime"); if (createTime == null) { return false; } if ((createTime.getTime() - now.getTime()) > EXPIRE_TIME) { return false; } return true; } private boolean validImageCode(final HttpSession session, final Credential credentials) { // 获取生成的图形验证码 String imageCode = (String) session.getAttribute("imageCode"); if (imageCode == null || imageCode.equals(" ")) { return false; } session.removeAttribute("imageCode"); // 获取提交的图形验证码 SSaturnCredential credential = (SSaturnCredential) credentials; String submitImageCode = credential.getImageCode(); if (submitImageCode != null && submitImageCode.equals(imageCode)) { return true; } return false; } private SResult responseByEvent(Event event, HttpSession session) { if ("success".equals(event.getId())) { session.removeAttribute("errorTimes"); SAccount account = (SAccount) session.getAttribute("account"); return SResult.success(account); } if ("successWithWarnings".equals(event.getId())) { session.removeAttribute("errorTimes"); return SResult.success("withWarning"); } else { setErrorTimes(session); return SResult.failure(SResultCode.ACCOUNT_LOGIN_FAIL); } }}

相关处理辅助类:

4.1、代替流程文件中的初始域数据类initialFlowSetupAction:

package com.saturn.handler.sso;import org.apache.commons.lang3.StringUtils;import org.jasig.cas.authentication.principal.Service;import org.jasig.cas.services.RegisteredService;import org.jasig.cas.services.RegisteredServiceAccessStrategy;import org.jasig.cas.services.ServicesManager;import org.jasig.cas.services.UnauthorizedServiceException;import org.jasig.cas.web.support.ArgumentExtractor;import org.jasig.cas.web.support.CookieRetrievingCookieGenerator;import org.jasig.cas.web.support.WebUtils;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.beans.factory.annotation.Value;import org.springframework.stereotype.Component;import javax.annotation.Resource;import javax.servlet.ServletContext;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpSession;import javax.validation.constraints.NotNull;import javax.validation.constraints.Size;import java.util.List;/** * this class is for * @since 1.8 */@Componentpublic class SInitServletContextAndHttpServletRequestHandler{   private final transient Logger logger = LoggerFactory.getLogger(this.getClass());   /**    * The services manager with access to the registry.    **/   @NotNull   @Autowired   private ServicesManager servicesManager;   /**    * CookieGenerator for the Warnings.    */   @NotNull   @Autowired   private CookieRetrievingCookieGenerator warnCookieGenerator;   /**    * CookieGenerator for the TicketGrantingTickets.    */   @NotNull   @Autowired   private CookieRetrievingCookieGenerator ticketGrantingTicketCookieGenerator;   /**    * Extractors for finding the service.    */   @NotNull   @Size (min = 1)   @Autowired   @Qualifier ("argumentExtractor")   private List
argumentExtractors; /** * If no authentication request from a service is present, halt and warn the user. */ private boolean hasAuthenticationRequest = true; public void initServletContextAndHttpServletRequest(HttpServletRequest request, Service service) { HttpSession session = request.getSession(); ServletContext context = session.getServletContext(); final String contextPath = context.getContextPath(); final String cookiePath = StringUtils.isNotBlank(contextPath) ? contextPath + '/' : "/"; if (StringUtils.isBlank(warnCookieGenerator.getCookiePath())) { logger.info("Setting path for cookies for warn cookie generator to: {} ", cookiePath); this.warnCookieGenerator.setCookiePath(cookiePath); } else { logger.debug("Warning cookie path is set to {} and path {}", warnCookieGenerator.getCookieDomain(), warnCookieGenerator.getCookiePath()); } if (StringUtils.isBlank(ticketGrantingTicketCookieGenerator.getCookiePath())) { logger.info("Setting path for cookies for TGC cookie generator to: {} ", cookiePath); this.ticketGrantingTicketCookieGenerator.setCookiePath(cookiePath); } else { logger.debug("TGC cookie path is set to {} and path {}", ticketGrantingTicketCookieGenerator.getCookieDomain(), ticketGrantingTicketCookieGenerator.getCookiePath()); } String ticketValue = this.ticketGrantingTicketCookieGenerator.retrieveCookieValue(request); Boolean cookieValue = Boolean.valueOf(this.ticketGrantingTicketCookieGenerator.retrieveCookieValue(request)); request.setAttribute("ticketGrantingTicketId", ticketValue); session.setAttribute("ticketGrantingTicketId", ticketValue); session.setAttribute("warnCookieValue", cookieValue); service = WebUtils.getService(this.argumentExtractors, request); if (service != null) { logger.debug("Placing service in context scope: [{}]", service.getId()); final RegisteredService registeredService = this.servicesManager.findServiceBy(service); if (registeredService != null && registeredService.getAccessStrategy().isServiceAccessAllowed()) { logger.debug("Placing registered service [{}] with id [{}] in context scope", registeredService.getServiceId(), registeredService.getId()); session.setAttribute("registeredService", registeredService); final RegisteredServiceAccessStrategy accessStrategy = registeredService.getAccessStrategy(); if (accessStrategy.getUnauthorizedRedirectUrl() != null) { logger.debug( "Placing registered service's unauthorized redirect url [{}] with id [{}] in context " + "scope", accessStrategy.getUnauthorizedRedirectUrl(), registeredService.getServiceId()); session.setAttribute("unauthorizedRedirectUrl", accessStrategy.getUnauthorizedRedirectUrl()); } } } else if (!this.hasAuthenticationRequest) { logger.warn( "No service authentication request is available at [{}]. CAS is configured to disable the flow.", request.getRequestURL()); throw new UnauthorizedServiceException("screen.service.required.message", "Service is required"); } session.setAttribute("service", service); } /** * Decide whether CAS should allow authentication requests * when no service is present in the request. Default is enabled. * @param enableFlowOnAbsentServiceRequest the enable flow on absent service request */ @Autowired public void setEnableFlowOnAbsentServiceRequest( @Value ("${create.sso.missing.service:true}") final boolean enableFlowOnAbsentServiceRequest) { this.hasAuthenticationRequest = enableFlowOnAbsentServiceRequest; }}

4.2、流程中的第一个处理节点ticketGrantingTicketCheck:

package com.saturn.handler.sso;import org.jasig.cas.CentralAuthenticationService;import org.jasig.cas.ticket.AbstractTicketException;import org.jasig.cas.ticket.Ticket;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.stereotype.Component;import org.springframework.util.StringUtils;import org.springframework.webflow.execution.Event;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpSession;import javax.validation.constraints.NotNull;/** * this class is for * @since 1.8 */@Componentpublic class STicketGrantingTicketCheckHandler{   private final transient Logger LOGGER = LoggerFactory.getLogger(this.getClass());   /**    * TGT does not exist event ID={@value}.    **/   private static final String NOT_EXISTS = "notExists";   /**    * TGT invalid event ID={@value}.    **/   private static final String INVALID = "invalid";   /**    * TGT valid event ID={@value}.    **/   private static final String VALID = "valid";   /**    * The Central authentication service.    */   @NotNull   private final CentralAuthenticationService centralAuthenticationService;   @Autowired   public STicketGrantingTicketCheckHandler(         @Qualifier ("centralAuthenticationService") final CentralAuthenticationService               centralAuthenticationService)   {      this.centralAuthenticationService = centralAuthenticationService;   }   /**    * \param[] a    * \return a    * \see    * \note    从session中获取ticket属性值,使用ticketGrantingTicketId命名属性时,cas可能会将此属性从session中移除,所以换了个名字“ticket”。    * \warning    */   public Event ticketGrantingTicketCheck(HttpServletRequest request)   {      HttpSession session = request.getSession();      final String tgtFromRequest = (String) request.getAttribute("ticket");      final String tgtFromSession = (String) session.getAttribute("ticket");      final String tgtId = tgtFromRequest != null ? tgtFromRequest : tgtFromSession;      if (!StringUtils.hasText(tgtId))      {         return new Event(this, NOT_EXISTS);      }      String eventId = INVALID;      try      {         final Ticket ticket = this.centralAuthenticationService.getTicket(tgtId, Ticket.class);         if (ticket != null && !ticket.isExpired())         {            eventId = VALID;         }      }      catch (final AbstractTicketException e)      {         LOGGER.trace("Could not retrieve ticket id {} from registry.", e);      }      return new Event(this, eventId);   }}

4.3、第二个节点:terminateSession

package com.saturn.handler.sso;import org.jasig.cas.CentralAuthenticationService;import org.jasig.cas.authentication.AuthenticationSystemSupport;import org.jasig.cas.authentication.DefaultAuthenticationSystemSupport;import org.jasig.cas.logout.LogoutRequest;import org.jasig.cas.web.support.CookieRetrievingCookieGenerator;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.stereotype.Component;import org.springframework.webflow.action.EventFactorySupport;import org.springframework.webflow.execution.Event;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;import javax.validation.constraints.NotNull;import java.util.List;/** * this class is for * @since 1.8 */@Componentpublic class STerminateSessionHandler{   /** Webflow event helper component. */   private final EventFactorySupport eventFactorySupport = new EventFactorySupport();   /** The CORE to which we delegate for all CAS functionality. */   @NotNull   @Autowired   @Qualifier ("centralAuthenticationService")   private CentralAuthenticationService centralAuthenticationService;   /** CookieGenerator for TGT Cookie. */   @NotNull   @Autowired   @Qualifier("ticketGrantingTicketCookieGenerator")   private CookieRetrievingCookieGenerator ticketGrantingTicketCookieGenerator;   /** CookieGenerator for Warn Cookie. */   @NotNull   @Autowired   @Qualifier("warnCookieGenerator")   private CookieRetrievingCookieGenerator warnCookieGenerator;   @NotNull   @Autowired(required=false)   @Qualifier("defaultAuthenticationSystemSupport")   private AuthenticationSystemSupport authenticationSystemSupport = new DefaultAuthenticationSystemSupport();   /**    * Creates a new instance with the given parameters.    */   public STerminateSessionHandler() {}   public Event terminate(HttpServletRequest request,HttpServletResponse response) {      // in login's webflow : we can get the value from context as it has already been stored      HttpSession session = request.getSession();      final String tgtFromRequest = (String) request.getAttribute("ticketGrantingTicketId");      final String tgtFromSession = (String) session.getAttribute("ticketGrantingTicketId");      String tgtId = tgtFromRequest != null ? tgtFromRequest : tgtFromSession;      // for logout, we need to get the cookie's value      if (tgtId == null) {         tgtId = this.ticketGrantingTicketCookieGenerator.retrieveCookieValue(request);      }      if (tgtId != null) {         final List
logoutRequests = this.centralAuthenticationService.destroyTicketGrantingTicket(tgtId); session.setAttribute("logoutRequests",logoutRequests); } this.ticketGrantingTicketCookieGenerator.removeCookie(response); this.warnCookieGenerator.removeCookie(response); return this.eventFactorySupport.success(this); }}

4.4、第三各节点(暂不考虑gatewayRequestCheck):serviceAuthorizationCheck

package com.saturn.handler.sso;import org.jasig.cas.authentication.principal.Service;import org.jasig.cas.services.RegisteredService;import org.jasig.cas.services.ServicesManager;import org.jasig.cas.services.UnauthorizedServiceException;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.stereotype.Component;import org.springframework.webflow.action.EventFactorySupport;import org.springframework.webflow.execution.Event;import javax.servlet.http.HttpSession;import javax.validation.constraints.NotNull;import java.net.URI;/** * \file       SServiceAuthorizationCheckHandler * \author     LiJiXiao * \date       2018/2/2 20:48 * \brief      L * \par Copyright (c): * Copyright (c) Saturn Team. All rights reserved. */@Componentpublic class SServiceAuthorizationCheckHandler{   private final transient Logger logger = LoggerFactory.getLogger(this.getClass());   @NotNull   private final ServicesManager servicesManager;   /**    * Initialize the component with an instance of the services manager.    * @param servicesManager the service registry instance.    */   @Autowired   public SServiceAuthorizationCheckHandler(@Qualifier ("servicesManager")                                    final ServicesManager servicesManager) {      this.servicesManager = servicesManager;   }   public Event check(final Service service, HttpSession session) throws UnauthorizedServiceException {      //No service == plain /login request. Return success indicating transition to the login form      if (service == null) {         return this.getEventFactorySupport().success(this);      }      if (this.servicesManager.getAllServices().isEmpty()) {         final String msg = String.format("No service definitions are found in the service manager. "                                          + "Service [%s] will not be automatically authorized to request authentication.", service.getId());         logger.warn(msg);         throw new UnauthorizedServiceException(UnauthorizedServiceException.CODE_EMPTY_SVC_MGMR);      }      final RegisteredService registeredService = this.servicesManager.findServiceBy(service);      if (registeredService == null) {         final String msg = String.format("Service Management: Unauthorized Service Access. "                                          + "Service [%s] is not found in service registry.", service.getId());         logger.warn(msg);         throw new UnauthorizedServiceException(UnauthorizedServiceException.CODE_UNAUTHZ_SERVICE, msg);      }      if (!registeredService.getAccessStrategy().isServiceAccessAllowed()) {         final String msg = String.format("Service Management: Unauthorized Service Access. "                                          + "Service [%s] is not allowed access via the service registry.", service.getId());         logger.warn(msg);         URI url = registeredService.getAccessStrategy().getUnauthorizedRedirectUrl();         session.setAttribute("unauthorizedRedirectUrl",url);         throw new UnauthorizedServiceException(UnauthorizedServiceException.CODE_UNAUTHZ_SERVICE, msg);      }      return this.getEventFactorySupport().success(this);   }   private EventFactorySupport getEventFactorySupport() {      return new EventFactorySupport();   }}

4.5、generateServiceTicket节点:

package com.saturn.handler.sso;import org.jasig.cas.CentralAuthenticationService;import org.jasig.cas.authentication.*;import org.jasig.cas.authentication.principal.Service;import org.jasig.cas.services.RegisteredService;import org.jasig.cas.services.ServicesManager;import org.jasig.cas.ticket.AbstractTicketException;import org.jasig.cas.ticket.InvalidTicketException;import org.jasig.cas.ticket.ServiceTicket;import org.jasig.cas.ticket.registry.TicketRegistrySupport;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.stereotype.Component;import org.springframework.webflow.action.EventFactorySupport;import org.springframework.webflow.core.collection.LocalAttributeMap;import org.springframework.webflow.execution.Event;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpSession;import javax.validation.constraints.NotNull;import java.net.URI;/** * this class is for * @since 1.8 */@Componentpublic class SGenerateServiceTicketHandler{   private final transient Logger logger = LoggerFactory.getLogger(this.getClass());   /**    * Instance of CentralAuthenticationService.    */   @NotNull   @Autowired   @Qualifier ("centralAuthenticationService")   private CentralAuthenticationService centralAuthenticationService;   @Autowired   @Qualifier("servicesManager")   private ServicesManager servicesManager;   @NotNull   @Autowired   @Qualifier("defaultAuthenticationSystemSupport")   private AuthenticationSystemSupport authenticationSystemSupport = new DefaultAuthenticationSystemSupport();   @Autowired   @Qualifier("defaultTicketRegistrySupport")   private TicketRegistrySupport ticketRegistrySupport;   public Event generateServiceTicket(Service service, HttpServletRequest request) {      HttpSession session = request.getSession();      final String tgtFromRequest = (String) request.getAttribute("ticketGrantingTicketId");      final String tgtFromSession = (String) session.getAttribute("ticketGrantingTicketId");      final String ticketGrantingTicket = tgtFromRequest != null ? tgtFromRequest : tgtFromSession;      try {         /**          * In the initial primary authentication flow, credentials are cached and available.          * Since they are authenticated as part of submission first, there is no need to doubly          * authenticate and verify credentials.          *          * In subsequent authentication flows where a TGT is available and only an ST needs to be          * created, there are no cached copies of the credential, since we do have a TGT available.          * So we will simply grab the available authentication and produce the final result based on that.          */         final Authentication authentication = ticketRegistrySupport.getAuthenticationFrom(ticketGrantingTicket);         if (authentication == null) {            throw new InvalidTicketException(new AuthenticationException(), ticketGrantingTicket);         }         final RegisteredService registeredService = servicesManager.findServiceBy(service);         session.setAttribute("registeredService",registeredService);         session.setAttribute("service",service);         URI url = registeredService.getAccessStrategy().getUnauthorizedRedirectUrl();         session.setAttribute("unauthorizedRedirectUrl", url);         final AuthenticationContextBuilder builder = new DefaultAuthenticationContextBuilder(               this.authenticationSystemSupport.getPrincipalElectionStrategy());         Credential cFromRequest = (Credential)request.getAttribute("credential");         Credential cFromSession = (Credential)session.getAttribute("credential");         Credential credential = cFromRequest != null ? cFromRequest : cFromSession;         credential = credential != null && org.apache.commons.lang3.StringUtils.isBlank(credential.getId()) ? null : credential;         final AuthenticationContext authenticationContext =               builder.collect(credential)                     .collect(authentication).build(service);         final ServiceTicket serviceTicketId = this.centralAuthenticationService               .grantServiceTicket(ticketGrantingTicket, service, authenticationContext);         request.setAttribute("serviceTicketId",serviceTicketId);         return this.getEventFactorySupport().success(this);      } catch (final AuthenticationException e) {         logger.error("Could not verify credentials to grant service ticket", e);      } catch (final AbstractTicketException e) {         if (e instanceof InvalidTicketException) {            this.centralAuthenticationService.destroyTicketGrantingTicket(ticketGrantingTicket);         }         return newEvent("sendTicketGrantingTicket", e);      }      return this.getEventFactorySupport().error(this);   }   public void setCentralAuthenticationService(final CentralAuthenticationService centralAuthenticationService) {      this.centralAuthenticationService = centralAuthenticationService;   }   public void setAuthenticationSystemSupport(final AuthenticationSystemSupport authenticationSystemSupport) {      this.authenticationSystemSupport = authenticationSystemSupport;   }   public void setTicketRegistrySupport(final TicketRegistrySupport ticketRegistrySupport) {      this.ticketRegistrySupport = ticketRegistrySupport;   }   public void setServicesManager(final ServicesManager servicesManager) {      this.servicesManager = servicesManager;   }   /**    * New event based on the id, which contains an error attribute referring to the exception occurred.    *    * @param id    the id    * @param error the error    * @return the event    */   private Event newEvent(final String id, final Exception error) {      return new Event(this, id, new LocalAttributeMap<>("error", error));   }   private EventFactorySupport getEventFactorySupport() {      return new EventFactorySupport();   }}

4.6、修改认证入口authenticationViaFormAction:

package com.saturn.handler.sso;import com.saturn.account.domain.model.SAccount;import org.apache.commons.lang3.StringUtils;import org.jasig.cas.CentralAuthenticationService;import org.jasig.cas.authentication.*;import org.jasig.cas.authentication.principal.Principal;import org.jasig.cas.authentication.principal.Service;import org.jasig.cas.ticket.AbstractTicketException;import org.jasig.cas.ticket.ServiceTicket;import org.jasig.cas.ticket.TicketCreationException;import org.jasig.cas.ticket.TicketGrantingTicket;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.binding.message.MessageBuilder;import org.springframework.binding.message.MessageContext;import org.springframework.stereotype.Component;import org.springframework.web.util.CookieGenerator;import org.springframework.webflow.core.collection.LocalAttributeMap;import org.springframework.webflow.execution.Event;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;import javax.validation.constraints.NotNull;import java.util.Iterator;import java.util.Map;/** * \file       SToAuthenticationHandler * \author     LiJiXiao * \date       2018/2/2 20:24 * \brief      L * \par Copyright (c): * Copyright (c) Saturn Team. All rights reserved. */@Componentpublic class SToAuthenticationHandler{   private static final String SUCCESS_WITH_WARNINGS = "successWithWarnings";   private static final String AUTHENTICATION_FAILURE = "authenticationFailure";   private static final String PUBLIC_WORKSTATION_ATTRIBUTE = "publicWorkstation";   private static final String WARN = "warn";   private final transient Logger LOGGER = LoggerFactory.getLogger(this.getClass());   @NotNull   @Autowired   @Qualifier ("centralAuthenticationService")   private CentralAuthenticationService centralAuthenticationService;   @NotNull   @Autowired   @Qualifier ("warnCookieGenerator")   private CookieGenerator warnCookieGenerator;   @NotNull   @Autowired (required = false)   @Qualifier ("defaultAuthenticationSystemSupport")   private AuthenticationSystemSupport authenticationSystemSupport = new DefaultAuthenticationSystemSupport();   public SToAuthenticationHandler()   {   }   public final Event submit(         HttpServletRequest request, HttpServletResponse response, Credential credential,         MessageContext messageContext)   {      return this.isRequestAskingForServiceTicket(request) ? this.grantServiceTicket(request, response, credential) :             this.createTicketGrantingTicket(request, response, credential, messageContext);   }   private boolean isRequestAskingForServiceTicket(HttpServletRequest request)   {      HttpSession session = request.getSession();      Service service = (Service) session.getAttribute("service");      String ticketGrantingTicketId = (String) session.getAttribute("ticketGrantingTicketId");      return StringUtils.isNotBlank(request.getParameter("renew")) && ticketGrantingTicketId != null &&             service != null;   }   private Event grantServiceTicket(HttpServletRequest request, HttpServletResponse response, Credential credential)   {      HttpSession session = request.getSession();      String ticketGrantingTicketId = (String) session.getAttribute("ticketGrantingTicketId");      try      {         Service service = (Service) session.getAttribute("service");         AuthenticationContextBuilder builder = new DefaultAuthenticationContextBuilder(               this.authenticationSystemSupport.getPrincipalElectionStrategy());         AuthenticationTransaction transaction = AuthenticationTransaction.wrap(credential);         this.authenticationSystemSupport.getAuthenticationTransactionManager().handle(transaction, builder);         AuthenticationContext authenticationContext = builder.build(service);         ServiceTicket serviceTicketId = this.centralAuthenticationService               .grantServiceTicket(ticketGrantingTicketId, service, authenticationContext);         request.setAttribute("serviceTicketId", serviceTicketId.getId());         putWarnCookieIfRequestParameterPresent(request, response);         return this.newEvent("warn");      }      catch (AuthenticationException var9)      {         return this.newEvent(AUTHENTICATION_FAILURE, var9);      }      catch (TicketCreationException var10)      {         this.LOGGER               .warn("Invalid attempt to access service using renew=true with different credential. Ending sso " +                     "session.");         this.centralAuthenticationService.destroyTicketGrantingTicket(ticketGrantingTicketId);         return this.newEvent("error");      }      catch (AbstractTicketException var11)      {         return this.newEvent("error", var11);      }   }   private Event createTicketGrantingTicket(         HttpServletRequest request, HttpServletResponse response, Credential credential,         MessageContext messageContext)   {      try      {         HttpSession session = request.getSession();         Service service = (Service) session.getAttribute("service");         AuthenticationContextBuilder builder = new DefaultAuthenticationContextBuilder(               this.authenticationSystemSupport.getPrincipalElectionStrategy());         AuthenticationTransaction transaction = AuthenticationTransaction.wrap(credential);         this.authenticationSystemSupport.getAuthenticationTransactionManager().handle(transaction, builder);         AuthenticationContext authenticationContext = builder.build(service);         // 获取账户信息         Authentication authentication = authenticationContext.getAuthentication();         Principal principal = authentication.getPrincipal();         SAccount account = (SAccount) principal.getAttributes().get("account");         session.setAttribute("account", account);         TicketGrantingTicket tgt =               this.centralAuthenticationService.createTicketGrantingTicket(authenticationContext);         String ticketValue = tgt != null ? tgt.getId() : null;         request.setAttribute("ticket", ticketValue);         session.setAttribute("ticket", ticketValue);         putWarnCookieIfRequestParameterPresent(request, response);         putPublicWorkstationToFlowIfRequestParameterPresent(request);         return this.addWarningMessagesToMessageContextIfNeeded(tgt, messageContext) ?                this.newEvent(SUCCESS_WITH_WARNINGS) : this.newEvent("success");      }      catch (AuthenticationException var9)      {         this.LOGGER.debug(var9.getMessage(), var9);         return this.newEvent("authenticationFailure", var9);      }      catch (Exception var10)      {         this.LOGGER.debug(var10.getMessage(), var10);         return this.newEvent("error", var10);      }   }   private boolean addWarningMessagesToMessageContextIfNeeded(         TicketGrantingTicket tgt, MessageContext messageContext)   {      boolean foundAndAddedWarnings = false;      Iterator var5 = tgt.getAuthentication().getSuccesses().entrySet().iterator();      while (var5.hasNext())      {         Map.Entry
entry = (Map.Entry) var5.next(); for (Iterator var7 = ((HandlerResult) entry.getValue()).getWarnings().iterator(); var7.hasNext(); foundAndAddedWarnings = true) { MessageDescriptor message = (MessageDescriptor) var7.next(); addWarningToContext(messageContext, message); } } return foundAndAddedWarnings; } private static void putPublicWorkstationToFlowIfRequestParameterPresent(HttpServletRequest request) { HttpSession session = request.getSession(); if (StringUtils.isNotBlank(request.getParameter(PUBLIC_WORKSTATION_ATTRIBUTE))) { session.setAttribute(PUBLIC_WORKSTATION_ATTRIBUTE, Boolean.TRUE); } } private Event newEvent(String id) { return new Event(this, id); } private Event newEvent(String id, Exception error) { return new Event(this, id, new LocalAttributeMap<>("error", error)); } private static void addWarningToContext(MessageContext context, MessageDescriptor warning) { MessageBuilder builder = (new MessageBuilder()).warning().code(warning.getCode()).defaultText(warning.getDefaultMessage()) .args(warning.getParams()); context.addMessage(builder.build()); } public void setCentralAuthenticationService(CentralAuthenticationService centralAuthenticationService) { this.centralAuthenticationService = centralAuthenticationService; } public void setWarnCookieGenerator(CookieGenerator warnCookieGenerator) { this.warnCookieGenerator = warnCookieGenerator; } public void setAuthenticationSystemSupport(AuthenticationSystemSupport authenticationSystemSupport) { this.authenticationSystemSupport = authenticationSystemSupport; } private void putWarnCookieIfRequestParameterPresent(HttpServletRequest request, HttpServletResponse response) { if (warnCookieGenerator != null) { LOGGER.debug("Evaluating request to determine if warning cookie should be generated"); if (StringUtils.isNotBlank(request.getParameter(WARN))) { warnCookieGenerator.addCookie(response, "true"); } else { warnCookieGenerator.removeCookie(response); } } else { LOGGER.debug("No warning cookie generator is defined"); } }}

5、记着修改访问路径映射。。。

 

 

转载于:https://my.oschina.net/u/3725601/blog/1618106

你可能感兴趣的文章
C++类模版学习笔记
查看>>
【LabVIEW技巧】工厂模式_简单工厂
查看>>
页面的Tab选项卡 简单实例
查看>>
FTP传输协议的应用详解
查看>>
r语言ggplot2误差棒图快速指南
查看>>
python之处理异常
查看>>
c++中的虚函数
查看>>
遍历form表单里面的表单元素,取其value
查看>>
Socket网络通讯开发总结之:Java 与 C进行Socket通讯(转)
查看>>
逆波兰算法解析计算公式
查看>>
PHP TP框架基础
查看>>
directive ngChecked
查看>>
面试110道题
查看>>
python 08 文件操作
查看>>
uiwebview 清缓存。,mark
查看>>
强势解决:windows 不能在本地计算机中起动Tomcat参考特定错误代码1
查看>>
IDEA中Junit使用注意事项
查看>>
java程序员面试进阶准备
查看>>
Cordova插件中JavaScript代码与Java的交互细节介绍
查看>>
SMSSDK验证码服务端校验接口
查看>>