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;
}
CAS 单点登录 移动端获取TGT、ST 已经移动端登录页面不进行跳转的设置的更多相关文章
- CAS学习笔记二:CAS单点登录流程
背景 由于公司项目甲方众多,各甲方为了统一登录用户体系实现单点登录(SSO)开始要求各乙方项目对接其搭建的CAS单点登录服务,有段时间对CAS的流程很迷,各厂商还有基于CAS进行二次开发的情况,所以对 ...
- jfinal集成cas单点认证实践
本示例jfinal集成cas单点认证,采用获取到登录用户session信息后,在本地站点备份一份session信息,主要做以下几个步骤: 1.站点引入响应jar包: 2.在web.xml中配置对应过滤 ...
- 如何不做登录请求而获取cookie到Jmeter里
如何不做登录请求而获取cookie到Jmeter里? 登录被测系统后,按F12,找到如下位置,将这个表格所有信息都复制到Jmeter的HTTP Cookie管理器元件,这样就可以不需要登录,能继续发送 ...
- cas 单点登录服务端客户端配置
首先,下载 cas-server-3.5.2-release http://pan.baidu.com/s/1GJ8Gs cas-client-3.2.1-release http://pan.bai ...
- CAS单点登录(SSO)服务端的部署和配置---连接MySQL进行身份认证
一.修改系统host,加入 127.0.0.1 server.test.com127.0.0.1 client1.test.com127.0.0.1 client2.test.com 二.安装grad ...
- cas单点登录如何获取更多信息
现在有个新的系统(SpringMVC+Spring+Mybatis),我为它添加了一个单点登录功能.只是在本地客户端的web.xml文件里,添加了以下配置 <!-- 用于单点退出,该过滤器用于实 ...
- CAS单点登录学习(一):服务端搭建
下载先在网上下载cas-server-3.5.2,将里面的cas-server-webapp-3.5.2.war放到tomcat的webapps目录下. https设置cas单点登默认使用的是http ...
- cas系列(一)--cas单点登录基本原理
(这段时间打算做单点登录,因此研究了一些cas资料并作为一个系列记录下来,一来可能会帮助一些人,二来对我自己所学知识也是一个巩固.) 一.为什么要实现单点登录 随着信息化不断发展,企业的信息化过程是一 ...
- CAS单点登录的原理
1.首先了解几个概念 1).TGC:Ticket-granting cookie,存放用户身份认证凭证的cookie,在浏览器和CAS Server间通讯时使用.2).TGT:ticket grant ...
随机推荐
- 【Redis学习之六】Redis数据类型:集合和有序集合
环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk8 redis-2.8.18 一.集合 Set无序的.去重的元素 ...
- linux 查看python安装路径,版本号
一.想要查看ubuntu中安装的python路径 方法一:whereis python 方法二:which python 二.想要查看ubuntu中安装的python版本号 python ...
- pandas.io.common.CParserError: Error tokenizing data. C error: Expected 1 fields in line 526, saw 5
pandas.io.common.CParserError: Error tokenizing data. C error: Expected 1 fields in line 526, saw 5 ...
- JDBC (29)
1.JDBC:就是一套API,由sun公司定义类或者定义的接口.(全称 java database connectivity:是Java访问数据库的标准规范),Java提供访问数据库规范称为JDBC, ...
- python递归的例子
例子1:递归实现嵌套列表求和 #encoding=utf-8 a=[[1,2,3], [4,5,6], [7,8,9]]def listsum(L): result=0 for i i ...
- android使用ARouter跳转activity(阿里巴巴开源的)
android使用ARouter跳转activity(阿里巴巴开源的) 使用ARouter方式,点击按钮跳转到其他activitypublic void buyOrSell(String str){ ...
- Django框架----分页器(paginator)
Django的分页器(paginator) view.py from django.shortcuts import render,HttpResponse # Create your views h ...
- Python爬虫【二】请求库requests
一.requests的常用请求方式 #各种请求方式:常用的就是requests.get()和requests.post() >>> import requests >>& ...
- 搭建ssm框架
我现在在着手搭建一个项目ssm+angularsJs的框架 以下是目录结构 将所有的依赖全部引入到父工程中,然后在子工程中需要的时候,再引入,父工程只是用来引入依赖 <!-- 集中定义依赖版本号 ...
- django加载静态文件
在一个网页中,不仅仅只有一个 html 骨架,还需要 css 样式文件. js 执行文件以及一些图片等,因此在 DTL 中加载静态文件是一个必须要解决的问题.在 DTL 中,使用 static 标签来 ...