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

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

修改web.xml




ticketValidationFilter
org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter


casServerUrlPrefix

http://passport.hivescm.com/cas


serverName

http://192.168.106.49:8080/order


useSession
true


redirectAfterValidation
false



ticketValidationFilter
/*

二。处理移动端通过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:
 *
 * 
    *
  • {@code POST /v1/tickets}
  • *
  • {@code POST /v1/tickets/{TGT-id}}
  • *
  • {@code DELETE /v1/tickets/{TGT-id}}
  • *
* * @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 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 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 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 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 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 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;
}





转载于:https://www.cnblogs.com/lvgg/p/7150352.html

你可能感兴趣的:(CAS 单点登录 移动端获取TGT、ST 已经移动端登录页面不进行跳转的设置)