• CAS 单点登录 移动端获取TGT、ST 已经移动端登录页面不进行跳转的设置


    一。设置移动客户端验证ST通过后,页面不进行302重定向跳转

    修改web.xml

    <!--***************************************************************** -->
    <!-- 校验ticket的过滤器 -->
    <filter>
    <filter-name>ticketValidationFilter</filter-name>
    <filter-class>org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter
    </filter-class>
    <init-param>
    <param-name>casServerUrlPrefix</param-name>
    <!-- SSO统一登录URL-->
    <param-value>http://passport.hivescm.com/cas</param-value>
    </init-param>
    <init-param>
    <param-name>serverName</param-name>
    <!--本客户端URL-->
    <param-value>http://192.168.106.49:8080/order</param-value>
    </init-param>
    <init-param>
    <param-name>useSession</param-name>
    <param-value>true</param-value>
    </init-param>
    <init-param>
    <param-name>redirectAfterValidation</param-name>
    <param-value>false</param-value>
    </init-param>
    </filter>
    <filter-mapping>
    <filter-name>ticketValidationFilter</filter-name>
    <url-pattern>/*</url-pattern>
    </filter-mapping>

    二。处理移动端通过ST访问另一个系统比较service通过

    1.移动端获取TGT的类,查看源码TicketsResource ,进行修改返回json数据

    package org.jasig.cas.support.rest;
    
    
    import com.fasterxml.jackson.core.JsonProcessingException;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.google.code.kaptcha.Constants;
    import com.hivecas.model.ConstantUtils;
    import com.hivecas.model.ResponseBean;
    import com.hivecas.model.UsernamePasswordStrongCredential;
    
    import org.apache.commons.lang3.StringUtils;
    import org.jasig.cas.CasProtocolConstants;
    import org.jasig.cas.CentralAuthenticationService;
    import org.jasig.cas.authentication.AuthenticationContext;
    import org.jasig.cas.authentication.AuthenticationContextBuilder;
    import org.jasig.cas.authentication.AuthenticationSystemSupport;
    import org.jasig.cas.authentication.AuthenticationException;
    import org.jasig.cas.authentication.AuthenticationTransaction;
    import org.jasig.cas.authentication.Credential;
    import org.jasig.cas.authentication.DefaultAuthenticationContextBuilder;
    import org.jasig.cas.authentication.DefaultAuthenticationSystemSupport;
    import org.jasig.cas.authentication.principal.Service;
    import org.jasig.cas.authentication.principal.ServiceFactory;
    import org.jasig.cas.ticket.InvalidTicketException;
    import org.jasig.cas.ticket.ServiceTicket;
    import org.jasig.cas.ticket.TicketGrantingTicket;
    import org.jasig.cas.ticket.registry.DefaultTicketRegistrySupport;
    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.http.HttpStatus;
    import org.springframework.http.MediaType;
    import org.springframework.http.ResponseEntity;
    import org.springframework.util.MultiValueMap;
    import org.springframework.web.bind.annotation.PathVariable;
    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.web.bind.annotation.RestController;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.validation.constraints.NotNull;
    import java.net.URI;
    import java.util.Formatter;
    import java.util.HashMap;
    import java.util.LinkedList;
    import java.util.List;
    import java.util.Map;
    
    /**
     * {@link RestController} implementation of CAS' REST API.
     *
     * This class implements main CAS RESTful resource for vending/deleting TGTs and vending STs:
     *
     * <ul>
     *     <li>{@code POST /v1/tickets}</li>
     *     <li>{@code POST /v1/tickets/{TGT-id}}</li>
     *     <li>{@code DELETE /v1/tickets/{TGT-id}}</li>
     * </ul>
     *
     * @author Dmitriy Kopylenko
     * @since 4.1.0
     */
    @RestController("ticketResourceRestController")
    public class TicketsResource {
    
        private static final Logger LOGGER = LoggerFactory.getLogger(TicketsResource.class);
    
        @Autowired
        @Qualifier("centralAuthenticationService")
        private CentralAuthenticationService centralAuthenticationService;
    
        @NotNull
        @Autowired(required=false)
        @Qualifier("defaultAuthenticationSystemSupport")
        private AuthenticationSystemSupport authenticationSystemSupport = new DefaultAuthenticationSystemSupport();
    
        @Autowired(required = false)
        private final CredentialFactory credentialFactory = new DefaultCredentialFactory();
    
        @Autowired
        @Qualifier("webApplicationServiceFactory")
        private ServiceFactory webApplicationServiceFactory;
    
        @Autowired
        @Qualifier("defaultTicketRegistrySupport")
        private TicketRegistrySupport ticketRegistrySupport = new DefaultTicketRegistrySupport();
    
        private final ObjectMapper jacksonObjectMapper = new ObjectMapper();
    
    
        /**
         * Create new ticket granting ticket.
         *
         * @param requestBody username and password application/x-www-form-urlencoded values
         * @param request raw HttpServletRequest used to call this method
         * @return ResponseEntity representing RESTful response
         * @throws JsonProcessingException in case of JSON parsing failure
         */
        @RequestMapping(value = "/tickets", method = RequestMethod.POST, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
        @ResponseBody 
        public final ResponseBean createTicketGrantingTicket(@RequestBody final MultiValueMap<String, String> requestBody,
                                                                       final HttpServletRequest request) throws JsonProcessingException {
        	  ResponseBean responseBean=new ResponseBean();
        	  try{
        		  
            	final String loginType = requestBody.getFirst("loginType");
                final Credential credential = this.credentialFactory.fromRequestBody(requestBody);
                final AuthenticationContextBuilder builder = new DefaultAuthenticationContextBuilder(
                        this.authenticationSystemSupport.getPrincipalElectionStrategy());
                final AuthenticationTransaction transaction =
                        AuthenticationTransaction.wrap(credential);
                this.authenticationSystemSupport.getAuthenticationTransactionManager().handle(transaction,  builder);
                final AuthenticationContext authenticationContext = builder.build();
                final TicketGrantingTicket tgtId = this.centralAuthenticationService.createMobileTicketGrantingTicket(authenticationContext,loginType);
                final URI ticketReference = new URI(request.getRequestURL().toString() + '/' + tgtId.getId());
                final Map<String, String> dataMap = new HashMap<>();
                dataMap.put("action", ticketReference.toString());
                responseBean.setData(dataMap);
                responseBean.setStatus(ConstantUtils.response_Status.SUCCESS);
                return responseBean;
            }
            catch(final AuthenticationException e) {
                responseBean.setMsg("无权限");
                responseBean.setStatus(ConstantUtils.response_Status.NO_AUTH);
                return responseBean;
            } catch (final BadRequestException e) {
                responseBean.setStatus(ConstantUtils.response_Status.FAIL);
                LOGGER.error(e.getMessage(), e);
                return responseBean;
            } catch (final Throwable e) {
            	 responseBean.setStatus(ConstantUtils.response_Status.FAIL);
                 LOGGER.error(e.getMessage(), e);
                 return responseBean;
            }
        }
    
        /**
         * Create new service ticket.
         *
         * @param requestBody service application/x-www-form-urlencoded value
         * @param tgtId ticket granting ticket id URI path param
         * @return {@link ResponseEntity} representing RESTful response
         */
        @RequestMapping(value = "/tickets/{tgtId:.+}", method = RequestMethod.POST, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
        @ResponseBody 
        public final ResponseBean createServiceTicket(@RequestBody final MultiValueMap<String, String> requestBody,
                                                                @PathVariable("tgtId") final String tgtId) {
        	 ResponseBean responseBean=new ResponseBean();
            try {
                final String serviceId = requestBody.getFirst(CasProtocolConstants.PARAMETER_SERVICE);
                final AuthenticationContextBuilder builder = new DefaultAuthenticationContextBuilder(
                        this.authenticationSystemSupport.getPrincipalElectionStrategy());
    
                final Service service = this.webApplicationServiceFactory.createService(serviceId);
                final AuthenticationContext authenticationContext =
                        builder.collect(this.ticketRegistrySupport.getAuthenticationFrom(tgtId)).build(service);
    
                final ServiceTicket serviceTicketId = this.centralAuthenticationService.grantServiceTicket(tgtId,
                        service, authenticationContext);
                responseBean.setStatus(ConstantUtils.response_Status.SUCCESS);
                final Map<String, String> dataMap = new HashMap<>();
                dataMap.put("serviceTicketId", serviceTicketId.getId());
                responseBean.setData(dataMap);
                return responseBean;
    
            } catch (final InvalidTicketException e) {
            	 responseBean.setStatus(ConstantUtils.response_Status.NO_AUTH);
            	 responseBean.setMsg("TGT不存在");
            	 return responseBean;
            } catch (final Exception e) {
            	LOGGER.error(e.getMessage(), e);
            	 responseBean.setStatus(ConstantUtils.response_Status.FAIL);
            	 return responseBean;
            }
        }
    
        /**
         * Destroy ticket granting ticket.
         *
         * @param tgtId ticket granting ticket id URI path param
         * @return {@link ResponseEntity} representing RESTful response. Signals
         * {@link HttpStatus#OK} when successful.
         */
        @RequestMapping(value = "/tickets/{tgtId:.+}", method = RequestMethod.DELETE)
        @ResponseBody
        public final ResponseBean deleteTicketGrantingTicket(@PathVariable("tgtId") final String tgtId) {
            this.centralAuthenticationService.destroyTicketGrantingTicket(tgtId);
            ResponseBean responseBean=new ResponseBean();
            responseBean.setStatus(ConstantUtils.response_Status.SUCCESS);
            responseBean.setMsg("删除成功");
            return responseBean;
        }
    
        public void setAuthenticationSystemSupport(final AuthenticationSystemSupport authenticationSystemSupport) {
            this.authenticationSystemSupport = authenticationSystemSupport;
        }
    
        public void setWebApplicationServiceFactory(final ServiceFactory webApplicationServiceFactory) {
            this.webApplicationServiceFactory = webApplicationServiceFactory;
        }
    
        public void setTicketRegistrySupport(final TicketRegistrySupport ticketRegistrySupport) {
            this.ticketRegistrySupport = ticketRegistrySupport;
        }
    
        public void setCentralAuthenticationService(final CentralAuthenticationService centralAuthenticationService) {
            this.centralAuthenticationService = centralAuthenticationService;
        }
    
        public CentralAuthenticationService getCentralAuthenticationService() {
            return centralAuthenticationService;
        }
    
        public AuthenticationSystemSupport getAuthenticationSystemSupport() {
            return authenticationSystemSupport;
        }
    
        public CredentialFactory getCredentialFactory() {
            return credentialFactory;
        }
    
        public ServiceFactory getWebApplicationServiceFactory() {
            return webApplicationServiceFactory;
        }
    
        public TicketRegistrySupport getTicketRegistrySupport() {
            return ticketRegistrySupport;
        }
    
        /**
         * Default implementation of CredentialFactory.
         */
        private static class DefaultCredentialFactory implements CredentialFactory {
        	
            @Override
            public Credential fromRequestBody(@NotNull final MultiValueMap<String, String> requestBody) {
                final String username = requestBody.getFirst("username");
                final String password = requestBody.getFirst("password");
                final String loginType = requestBody.getFirst("loginType");
                if(username == null || password == null||loginType==null) {
                    throw new BadRequestException("Invalid payload. 'username' and 'password' form fields are required.");
                }
                if(!StringUtils.equals(loginType, ConstantUtils.loginType.MOBILE)){
                	  throw new BadRequestException("Invalid payload. 'loginType' is wrong.");
                }
                return new UsernamePasswordStrongCredential(username, password,loginType);
            }
        }
    
        /**
         * Exception to indicate bad payload.
         */
        private static class BadRequestException extends IllegalArgumentException {
            private static final long serialVersionUID = 6852720596988243487L;
    
            /**
             * Ctor.
             * @param msg error message
             */
            BadRequestException(final String msg) {
                super(msg);
            }
        }
    }
    

      2.返回responsebean

    package com.hivecas.model;
    
    import java.util.Map;
    
    public class ResponseBean {
    	//返回状态 1 成功 2 失败
    	public String status;
    	//返回数据 
    	public Map data; 
    	//返回信息
    	public String msg;
    	
    	public String getStatus() {
    		return status;
    	}
    	public void setStatus(String status) {
    		this.status = status;
    	}
    	public Map getData() {
    		return data;
    	}
    	public void setData(Map data) {
    		this.data = data;
    	}
    	public String getMsg() {
    		return msg;
    	}
    	public void setMsg(String msg) {
    		this.msg = msg;
    	}
    }
    

      3.在源码CentralAuthenticationServiceImpl添加createMobileTicketGrantingTicket方法,将移动登录的类型loginType 设置到TGT中

     
        @Audit(
            action="TICKET_GRANTING_TICKET",
            actionResolverName="CREATE_TICKET_GRANTING_TICKET_RESOLVER",
            resourceResolverName="CREATE_TICKET_GRANTING_TICKET_RESOURCE_RESOLVER")
        @Timed(name = "CREATE_TICKET_GRANTING_TICKET_TIMER")
        @Metered(name = "CREATE_TICKET_GRANTING_TICKET_METER")
        @Counted(name="CREATE_TICKET_GRANTING_TICKET_COUNTER", monotonic=true)
        public TicketGrantingTicket createMobileTicketGrantingTicket(final AuthenticationContext context,final String loginType)
                throws AuthenticationException, AbstractTicketException {
            final Authentication authentication = context.getAuthentication();
            final TicketGrantingTicketFactory factory = this.ticketFactory.get(TicketGrantingTicket.class);
            
            final TicketGrantingTicket ticketGrantingTicket = factory.create(authentication,loginType);
    
            this.ticketRegistry.addTicket(ticketGrantingTicket);
    
            doPublishEvent(new CasTicketGrantingTicketCreatedEvent(this, ticketGrantingTicket));
    
            return ticketGrantingTicket;
        }
    

      4.源码TicketGrantingTicket添加获取getLoginType方法

    public interface TicketGrantingTicket extends Ticket {
    
        /** The prefix to use when generating an id for a Ticket Granting Ticket. */
        String PREFIX = "TGT";
        
         String getLoginType();
        
    

      5.这就可以在客户端请求ST票据验证时,不进行service的url比较验证,直接通过。位置在源码CentralAuthenticationServiceImpl类中

     @Audit(
            action="SERVICE_TICKET_VALIDATE",
            actionResolverName="VALIDATE_SERVICE_TICKET_RESOLVER",
            resourceResolverName="VALIDATE_SERVICE_TICKET_RESOURCE_RESOLVER")
        @Timed(name="VALIDATE_SERVICE_TICKET_TIMER")
        @Metered(name="VALIDATE_SERVICE_TICKET_METER")
        @Counted(name="VALIDATE_SERVICE_TICKET_COUNTER", monotonic=true)
        @Override
        public Assertion validateServiceTicket(final String serviceTicketId, final Service service) throws AbstractTicketException {
            final RegisteredService registeredService = this.servicesManager.findServiceBy(service);
            verifyRegisteredServiceProperties(registeredService, service);
    
            final ServiceTicket serviceTicket =  this.ticketRegistry.getTicket(serviceTicketId, ServiceTicket.class);
            if (serviceTicket == null) {
                logger.info("Service ticket [{}] does not exist.", serviceTicketId);
                throw new InvalidTicketException(serviceTicketId);
            }
            final TicketGrantingTicket root ;
            try {
                synchronized (serviceTicket) {
                    if (serviceTicket.isExpired()) {
                        logger.info("ServiceTicket [{}] has expired.", serviceTicketId);
                        throw new InvalidTicketException(serviceTicketId);
                    }
                    
                     root = serviceTicket.getGrantingTicket().getRoot();
                    if(root!=null){
                    	String loginType=root.getLoginType();
                    	if(StringUtils.isNotBlank(loginType)||StringUtils.equalsIgnoreCase(loginType, ConstantUtils.loginType.PC)){
                    		 if (!serviceTicket.isValidFor(service)) {
                                 logger.error("Service ticket [{}] with service [{}] does not match supplied service [{}]",
                                         serviceTicketId, serviceTicket.getService().getId(), service);
                                 throw new UnrecognizableServiceForServiceTicketValidationException(serviceTicket.getService());
                             }
                    	}
                    }
                }
    
               // final TicketGrantingTicket root = serviceTicket.getGrantingTicket().getRoot();
                final Authentication authentication = getAuthenticationSatisfiedByPolicy(
                        root, new ServiceContext(serviceTicket.getService(), registeredService));
                final Principal principal = authentication.getPrincipal();
    
                final RegisteredServiceAttributeReleasePolicy attributePolicy = registeredService.getAttributeReleasePolicy();
                logger.debug("Attribute policy [{}] is associated with service [{}]", attributePolicy, registeredService);
                
                @SuppressWarnings("unchecked")
                final Map<String, Object> attributesToRelease = attributePolicy != null
                        ? attributePolicy.getAttributes(principal) : Collections.EMPTY_MAP;
                
                final String principalId = registeredService.getUsernameAttributeProvider().resolveUsername(principal, service);
                final Principal modifiedPrincipal = this.principalFactory.createPrincipal(principalId, attributesToRelease);
                final AuthenticationBuilder builder = DefaultAuthenticationBuilder.newInstance(authentication);
                builder.setPrincipal(modifiedPrincipal);
    
                final Assertion assertion = new ImmutableAssertion(
                        builder.build(),
                        serviceTicket.getGrantingTicket().getChainedAuthentications(),
                        serviceTicket.getService(),
                        serviceTicket.isFromNewLogin());
    
                doPublishEvent(new CasServiceTicketValidatedEvent(this, serviceTicket, assertion));
    
                return assertion;
    
            } finally {
                if (serviceTicket.isExpired()) {
                    this.ticketRegistry.deleteTicket(serviceTicketId);
                }
            }
        }
        
        @Audit(
            action="TICKET_GRANTING_TICKET",
            actionResolverName="CREATE_TICKET_GRANTING_TICKET_RESOLVER",
            resourceResolverName="CREATE_TICKET_GRANTING_TICKET_RESOURCE_RESOLVER")
        @Timed(name = "CREATE_TICKET_GRANTING_TICKET_TIMER")
        @Metered(name = "CREATE_TICKET_GRANTING_TICKET_METER")
        @Counted(name="CREATE_TICKET_GRANTING_TICKET_COUNTER", monotonic=true)
        @Override
        public TicketGrantingTicket createTicketGrantingTicket(final AuthenticationContext context)
                throws AuthenticationException, AbstractTicketException {
    
            final Authentication authentication = context.getAuthentication();
            final TicketGrantingTicketFactory factory = this.ticketFactory.get(TicketGrantingTicket.class);
            final TicketGrantingTicket ticketGrantingTicket = factory.create(authentication);
    
            this.ticketRegistry.addTicket(ticketGrantingTicket);
    
            doPublishEvent(new CasTicketGrantingTicketCreatedEvent(this, ticketGrantingTicket));
    
            return ticketGrantingTicket;
    }





  • 相关阅读:
    Haproxy 配置项及配置实例-Haproxy入门教程
    Spring Boot 配置-Spring Boot教程深入浅出系列
    RMI 接口和类概述-RMI快速入门教程
    分布式和非分布式模型对比-RMI快速入门教程
    RMI分布式对象模型-RMI快速入门教程
    RMI介绍-RMI快速入门教程
    Qt编写可视化大屏电子看板系统17-柱状堆积图
    Qt开发经验小技巧161-165
    Qt编写安防视频监控系统60-子模块4云台控制
    MyBatis的关联映射,resultMap元素之collection子元素,实现一对多关联关系(节选自:Java EE企业级应用开发教程)
  • 原文地址:https://www.cnblogs.com/lvgg/p/7150352.html
Copyright © 2020-2023  润新知