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;
}





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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值