CAS REST

上级 9ed7b08c
......@@ -6,6 +6,12 @@ dependencies {
//local jars
compile fileTree(dir: '../maxkey-lib/*/', include: '*.jar')
testCompile group: 'org.pac4j', name: 'pac4j-core', version: '3.1.0'
// https://mvnrepository.com/artifact/org.pac4j/pac4j-cas
testCompile group: 'org.pac4j', name: 'pac4j-cas', version: '3.1.0'
compile project(":maxkey-core")
compile project(":maxkey-persistence")
compile project(":maxkey-protocols:maxkey-protocol-authorize")
......
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
*
*/
package org.maxkey.authz.cas.endpoint;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.maxkey.authn.BasicAuthentication;
import org.maxkey.authn.realm.AbstractAuthenticationRealm;
import org.maxkey.authz.cas.endpoint.ticket.CasConstants;
import org.maxkey.authz.cas.endpoint.ticket.ServiceTicketImpl;
import org.maxkey.authz.cas.endpoint.ticket.TicketGrantingTicketImpl;
import org.maxkey.domain.UserInfo;
import org.maxkey.domain.apps.AppsCasDetails;
import org.maxkey.persistence.db.PasswordPolicyValidator;
import org.maxkey.web.WebContext;
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.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.AuthenticationException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
/**
* @author Crystal.Sea
* https://apereo.github.io/cas/6.2.x/protocol/REST-Protocol.html
*/
@Controller
public class CasRestV1Endpoint extends CasBaseAuthorizeEndpoint{
final static Logger _logger = LoggerFactory.getLogger(CasRestV1Endpoint.class);
@Autowired
protected PasswordPolicyValidator passwordPolicyValidator;
@Autowired
@Qualifier("authenticationRealm")
protected AbstractAuthenticationRealm authenticationRealm;
@RequestMapping(value="/authz/cas/v1/tickets",
method=RequestMethod.POST,
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public ResponseEntity<String> casLoginRestTickets(
HttpServletRequest request,
HttpServletResponse response,
@RequestParam(value=CasConstants.PARAMETER.SERVICE,required=false) String casService,
@RequestParam(value=CasConstants.PARAMETER.REST_USERNAME,required=true) String username,
@RequestParam(value=CasConstants.PARAMETER.REST_PASSWORD,required=true) String password){
try {
if (password == null || password.isEmpty()) {
throw new BadCredentialsException("No credentials are provided or extracted to authenticate the REST request");
}
AbstractAuthenticationRealm authenticationRealm =
(AbstractAuthenticationRealm) WebContext.getBean("authenticationRealm");
UserInfo loadeduserInfo = authenticationRealm.loadUserInfo(username, "");
if (loadeduserInfo != null) {
authenticationRealm.passwordMatches(loadeduserInfo, password);
passwordPolicyValidator.passwordPolicyValid(loadeduserInfo);
WebContext.setUserInfo(loadeduserInfo);
BasicAuthentication authentication =new BasicAuthentication();
authentication.setUsername(username);
authentication.setPassword(password);
authentication.setAuthType("basic");
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
new UsernamePasswordAuthenticationToken(
authentication,
"PASSWORD",
authenticationRealm.grantAuthority(loadeduserInfo)
);
authentication.setAuthenticated(true);
WebContext.setAuthentication(usernamePasswordAuthenticationToken);
WebContext.setUserInfo(loadeduserInfo);
authenticationRealm.insertLoginHistory(loadeduserInfo, "CAS", "", "", "SUCCESS");
TicketGrantingTicketImpl ticketGrantingTicket=new TicketGrantingTicketImpl("Random",WebContext.getAuthentication(),null);
String ticket=ticketServices.createTicket(ticketGrantingTicket);
String location = applicationConfig.getServerPrefix()+"/authz/cas/v1/tickets/" + ticket;
HttpHeaders headers = new HttpHeaders();
headers.add("location", location);
return new ResponseEntity<>("Location: " + location, headers ,HttpStatus.CREATED);
}else {
String message = WebContext.getI18nValue("login.error.username");
_logger.debug("login user " + username + " not in this System ." + message);
throw new BadCredentialsException(WebContext.getI18nValue("login.error.username"));
}
} catch (final AuthenticationException e) {
_logger.error("BadCredentialsException ", e);
return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST);
} catch (final Exception e) {
_logger.error("Exception ", e);
return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@RequestMapping(value="/authz/cas/v1/tickets/{ticketGrantingTicket}",
method=RequestMethod.POST,
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public ResponseEntity<String> requestServiceTicket(
HttpServletRequest request,
HttpServletResponse response,
@PathVariable("ticketGrantingTicket") String ticketGrantingTicket,
@RequestParam(value=CasConstants.PARAMETER.SERVICE,required=false) String casService,
@RequestParam(value=CasConstants.PARAMETER.RENEW,required=false) String renew,
@RequestParam(value=CasConstants.PARAMETER.REST_USERNAME,required=false) String username,
@RequestParam(value=CasConstants.PARAMETER.REST_PASSWORD,required=false) String password){
try {
TicketGrantingTicketImpl ticketGrantingTicketImpl =
(TicketGrantingTicketImpl) ticketServices.consumeTicket(ticketGrantingTicket);
AppsCasDetails casDetails=new AppsCasDetails();
if(casService.startsWith("http")) {
casDetails.setService(casService);
List<AppsCasDetails> casDetailsList=casDetailsService.query(casDetails);
casDetails=(casDetailsList!=null && casDetailsList.size()==1)?casDetailsList.get(0):null;
}else {
casDetails=casDetailsService.getAppDetails(casService);
}
ServiceTicketImpl serviceTicket=new ServiceTicketImpl(ticketGrantingTicketImpl.getAuthentication(),casDetails);
String ticket=ticketServices.createTicket(serviceTicket);
return new ResponseEntity<>(ticket, HttpStatus.OK);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return new ResponseEntity<>("", HttpStatus.BAD_REQUEST);
}
@RequestMapping(value="/authz/cas/v1/users",
method=RequestMethod.POST,
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public ResponseEntity<String> casLoginRestUsers(
HttpServletRequest request,
HttpServletResponse response,
@RequestParam(value=CasConstants.PARAMETER.SERVICE,required=false) String casService,
@RequestParam(value=CasConstants.PARAMETER.REST_USERNAME,required=true) String username,
@RequestParam(value=CasConstants.PARAMETER.REST_PASSWORD,required=true) String password){
return null;
}
}
......@@ -57,6 +57,10 @@ public class CasConstants {
/** Constant representing the pgtIou parameter in the request. */
public static final String PROXY_GRANTING_TICKET_IOU = "pgtIou";
public static final String REST_USERNAME = "username";
public static final String REST_PASSWORD = "password";
}
public static final class FORMAT_TYPE {
......@@ -83,6 +87,8 @@ public class CasConstants {
public static final String PROXY_GRANTING_TICKET_PREFIX = "PGT";
/** The prefix to use when generating an id for a Proxy Granting Ticket IOU. */
public static final String PROXY_GRANTING_TICKET_IOU_PREFIX = "PGTIOU";
public static final String TICKET_GRANTING_TICKET_PREFIX = "TGT";
}
/* CAS Protocol Error Codes. **/
......
package org.maxkey.authz.cas.endpoint.ticket;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import java.io.Serializable;
/**
* Strategy that determines if the ticket is expired. Implementations of the
* Expiration Policy define their own rules on what they consider an expired
* Ticket to be.
*
* @author Scott Battaglia
* @see Ticket
* @since 3.0.0
*/
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
public interface ExpirationPolicy extends Serializable {
/**
* Method to determine if a Ticket has expired or not, based on the policy.
*
* @param ticketState The snapshot of the current ticket state
* @return true if the ticket is expired, false otherwise.
*/
boolean isExpired(TicketState ticketState);
/**
* Method to determine the actual TTL of a ticket, based on the policy.
*
* @param ticketState The snapshot of the current ticket state
* @return The time to live in seconds. A zero value indicates the time duration is not supported or is inactive.
*/
default Long getTimeToLive(final TicketState ticketState) {
return getTimeToLive();
}
/**
* Describes the time duration where this policy should consider the item alive.
* Once this time passes, the item is considered expired and dead.
*
* @return time to live in seconds. A zero value indicates the time duration is not supported or is inactive.
*/
Long getTimeToLive();
/**
* Describes the idle time duration for the item.
*
* @return idle time in seconds. A zero value indicates the time duration is not supported or is inactive. Unit of measure is defined by the implementation.
*/
Long getTimeToIdle();
/**
* Gets name of this expiration policy.
*
* @return the name
*/
String getName();
}
package org.maxkey.authz.cas.endpoint.ticket;
import org.maxkey.authz.cas.endpoint.ticket.proxy.ProxyGrantingTicket;
import org.springframework.security.core.Authentication;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
/**
* Interface for a Service Ticket. A service ticket is used to grant access to a
* specific service for a principal. A Service Ticket is generally a one-time
* use ticket.
*
* @author Scott Battaglia
* @since 3.0.0
*/
@JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include= JsonTypeInfo.As.PROPERTY)
public interface ServiceTicket extends Ticket {
/**
* Prefix generally applied to unique ids generated
* by UniqueTicketIdGenerator.
*/
String PREFIX = "ST";
/**
* Retrieve the service this ticket was given for.
*
* @return the server.
*/
Service getService();
/**
* Determine if this ticket was created at the same time as a
* TicketGrantingTicket.
*
* @return true if it is, false otherwise.
*/
boolean isFromNewLogin();
/**
* Attempts to ensure that the service specified matches the service associated with the ticket.
*
* @param service The incoming service to match this service ticket against.
* @return true, if the match is successful.
*/
boolean isValidFor(Service service);
/**
* Method to grant a TicketGrantingTicket from this service to the
* authentication. Analogous to the ProxyGrantingTicket.
*
* @param id The unique identifier for this ticket.
* @param authentication The Authentication we wish to grant a ticket for.
* @param expirationPolicy expiration policy associated with this ticket
* @return The ticket granting ticket.
* @throws AbstractTicketException ticket exception thrown when generating the ticket
* @since 4.2
*/
ProxyGrantingTicket grantProxyGrantingTicket(String id,
Authentication authentication,
ExpirationPolicy expirationPolicy)
throws Exception;
}
......@@ -18,6 +18,7 @@
package org.maxkey.authz.cas.endpoint.ticket;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.maxkey.authz.cas.endpoint.ticket.proxy.ProxyGrantingTicket;
import org.maxkey.domain.apps.AppsCasDetails;
import org.springframework.security.core.Authentication;
......@@ -33,7 +34,7 @@ import javax.persistence.Column;
* @since 3.0.0
*/
public class ServiceTicketImpl extends AbstractTicket {
public class ServiceTicketImpl extends AbstractTicket implements ServiceTicket{
private static final long serialVersionUID = -4223319704861765405L;
......@@ -112,4 +113,23 @@ public class ServiceTicketImpl extends AbstractTicket {
.isEquals();
}
@Override
public Service getService() {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean isFromNewLogin() {
// TODO Auto-generated method stub
return false;
}
@Override
public ProxyGrantingTicket grantProxyGrantingTicket(String id, Authentication authentication,
ExpirationPolicy expirationPolicy) throws Exception {
// TODO Auto-generated method stub
return null;
}
}
package org.maxkey.authz.cas.endpoint.ticket;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import org.maxkey.domain.apps.AppsCasDetails;
import org.springframework.security.core.Authentication;
/**
* Interface for a ticket granting ticket. A TicketGrantingTicket is the main
* access into the CAS service layer. Without a TicketGrantingTicket, a user of
* CAS cannot do anything.
*
* @author Scott Battaglia
* @since 3.0.0
*/
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
public interface TicketGrantingTicket extends Ticket {
/**
* The prefix to use when generating an id for a Ticket Granting Ticket.
*/
String PREFIX = "TGT";
/**
* Method to retrieve the authentication.
*
* @return the authentication
*/
Authentication getAuthentication();
/**
* Grant a ServiceTicket for a specific service.
*
* @param id The unique identifier for this ticket.
* @param service The service for which we are granting a ticket
* @param expirationPolicy the expiration policy.
* @param credentialProvided current credential event for issuing this ticket. Could be null.
* @param onlyTrackMostRecentSession track the most recent session by keeping the latest service ticket
* @return the service ticket granted to a specific service for the principal of the TicketGrantingTicket
*/
ServiceTicket grantServiceTicket(String id, Service service,
AppsCasDetails casDetails,
ExpirationPolicy expirationPolicy,
boolean credentialProvided,
boolean onlyTrackMostRecentSession);
/**
* Gets an immutable map of service ticket and services accessed by this ticket-granting ticket.
*
* @return an immutable map of service ticket and services accessed by this ticket-granting ticket.
*/
Map<String, Service> getServices();
/**
* Gets proxy granting tickets created by this TGT.
*
* @return the proxy granting tickets
*/
Map<String, Service> getProxyGrantingTickets();
/**
* Remove all services of the TGT (at logout).
*/
void removeAllServices();
/**
* Convenience method to determine if the TicketGrantingTicket is the root
* of the hierarchy of tickets.
*
* @return true if it has no parent, false otherwise.
*/
boolean isRoot();
/**
* Gets the ticket-granting ticket at the root of the ticket hierarchy.
*
* @return Non -null root ticket-granting ticket.
*/
TicketGrantingTicket getRoot();
/**
* Gets all authentications ({@link #getAuthentication()} from this
* instance and all dependent tickets that reference this one.
*
* @return Non -null list of authentication associated with this ticket in leaf-first order.
*/
List<Authentication> getChainedAuthentications();
/**
* Gets the service that produced a proxy-granting ticket.
*
* @return Service that produced proxy-granting ticket or null if this is not a proxy-granting ticket.
* @since 4.1
*/
Service getProxiedBy();
/**
* Gets descendant tickets. These are generally ticket ids
* whose life-line is separate from the TGT until and unless
* the TGT goes away entirely. Things such as OAuth access tokens
* are a good example of such linked tickets.
*
* @return the descendant tickets
* @since 5.1
*/
default Collection<String> getDescendantTickets() {
return new HashSet<>(0);
}
}
package org.maxkey.authz.cas.endpoint.ticket;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import org.apache.commons.lang3.StringUtils;
import org.maxkey.domain.apps.AppsCasDetails;
import org.springframework.lang.NonNull;
import org.springframework.security.core.Authentication;
import javax.persistence.Column;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
/**
* Concrete implementation of a TicketGrantingTicket. A TicketGrantingTicket is
* the global identifier of a principal into the system. It grants the Principal
* single-sign on access to any service that opts into single-sign on.
* Expiration of a TicketGrantingTicket is controlled by the ExpirationPolicy
* specified as object creation.
*
* @author Scott Battaglia
* @since 3.0.0
*/
@Entity
@Table(name = "TICKETGRANTINGTICKET")
@DiscriminatorColumn(name = "TYPE")
@DiscriminatorValue(TicketGrantingTicket.PREFIX)
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
public class TicketGrantingTicketImpl extends AbstractTicket implements TicketGrantingTicket {
/**
* Unique Id for serialization.
*/
private static final long serialVersionUID = -8608149809180911599L;
/**
* The authenticated object for which this ticket was generated for.
*/
@Lob
@Column(name = "AUTHENTICATION", nullable = false, length = Integer.MAX_VALUE)
private Authentication authentication;
/**
* Service that produced a proxy-granting ticket.
*/
@Lob
@Column(name = "PROXIED_BY", length = Integer.MAX_VALUE)
private Service proxiedBy;
/**
* The services associated to this ticket.
*/
@Lob
@Column(name = "SERVICES_GRANTED_ACCESS_TO", nullable = false, length = Integer.MAX_VALUE)
private HashMap<String, Service> services = new HashMap<>();
/**
* The {@link TicketGrantingTicket} this is associated with.
*/
@ManyToOne(targetEntity = TicketGrantingTicketImpl.class)
private TicketGrantingTicket ticketGrantingTicket;
/**
* The PGTs associated to this ticket.
*/
@Lob
@Column(name = "PROXY_GRANTING_TICKETS", nullable = false, length = Integer.MAX_VALUE)
private HashMap<String, Service> proxyGrantingTickets = new HashMap<>();
/**
* The ticket ids which are tied to this ticket.
*/
@Lob
@Column(name = "DESCENDANT_TICKETS", nullable = false, length = Integer.MAX_VALUE)
private HashSet<String> descendantTickets = new HashSet<>();
/**
* Constructs a new TicketGrantingTicket.
* May throw an {@link IllegalArgumentException} if the Authentication object is null.
*
* @param id the id of the Ticket
* @param proxiedBy Service that produced this proxy ticket.
* @param parentTicketGrantingTicket the parent ticket
* @param authentication the Authentication request for this ticket
* @param policy the expiration policy for this ticket.
*/
@JsonCreator
public TicketGrantingTicketImpl(@JsonProperty("id") final String id, @JsonProperty("proxiedBy") final Service proxiedBy,
@JsonProperty("ticketGrantingTicket") final TicketGrantingTicket parentTicketGrantingTicket,
@NonNull @JsonProperty("authentication") final Authentication authentication, @JsonProperty("expirationPolicy") final ExpirationPolicy policy) {
if (parentTicketGrantingTicket != null && proxiedBy == null) {
throw new IllegalArgumentException("Must specify proxiedBy when providing parent TGT");
}
this.ticketGrantingTicket = parentTicketGrantingTicket;
this.authentication = authentication;
this.proxiedBy = proxiedBy;
}
/**
* Constructs a new TicketGrantingTicket without a parent
* TicketGrantingTicket.
*
* @param id the id of the Ticket
* @param authentication the Authentication request for this ticket
* @param policy the expiration policy for this ticket.
*/
public TicketGrantingTicketImpl(final String id, final Authentication authentication, final ExpirationPolicy policy) {
this(id, null, null, authentication, policy);
}
@Override
public synchronized ServiceTicket grantServiceTicket(final String id, final Service service, AppsCasDetails casDetails,final ExpirationPolicy expirationPolicy,
final boolean credentialProvided, final boolean onlyTrackMostRecentSession) {
final ServiceTicket serviceTicket = new ServiceTicketImpl(authentication,casDetails);
return serviceTicket;
}
/**
* Normalize the path of a service by removing the query string and everything after a semi-colon.
*
* @param service the service to normalize
* @return the normalized path
private static String normalizePath(final Service service) {
String path = service.getId();
path = StringUtils.substringBefore(path, "?");
path = StringUtils.substringBefore(path, ";");
path = StringUtils.substringBefore(path, "#");
return path;
}
*/
/**
* Remove all services of the TGT (at logout).
*/
@Override
public void removeAllServices() {
this.services.clear();
}
public String getPrefix() {
return TicketGrantingTicket.PREFIX;
}
@Override
public Map<String, Service> getServices() {
// TODO Auto-generated method stub
return null;
}
@Override
public Map<String, Service> getProxyGrantingTickets() {
// TODO Auto-generated method stub
return null;
}
@Override
public Service getProxiedBy() {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean isRoot() {
// TODO Auto-generated method stub
return false;
}
@Override
public TicketGrantingTicket getRoot() {
// TODO Auto-generated method stub
return null;
}
@Override
public List<Authentication> getChainedAuthentications() {
// TODO Auto-generated method stub
return null;
}
}
package org.maxkey.authz.cas.endpoint.ticket;
import java.time.ZonedDateTime;
import org.springframework.security.core.Authentication;
/**
* @author Scott Battaglia
* @since 3.0.0
*/
public interface TicketState {
/**
* Returns the number of times a ticket was used.
*
* @return the number of times the ticket was used.
*/
int getCountOfUses();
/**
* Returns the last time the ticket was used.
*
* @return the last time the ticket was used.
*/
ZonedDateTime getLastTimeUsed();
/**
* Get the second to last time used.
*
* @return the previous time used.
*/
ZonedDateTime getPreviousTimeUsed();
/**
* Get the time the ticket was created.
*
* @return the creation time of the ticket.
*/
ZonedDateTime getCreationTime();
/**
* Authentication information from the ticket. This may be null.
*
* @return the authentication information.
*/
Authentication getAuthentication();
/**
* Method to retrieve the TicketGrantingTicket that granted this ticket.
*
* @return the ticket or null if it has no parent
*/
TicketGrantingTicket getTicketGrantingTicket();
/**
* Records the <i>previous</i> last time this ticket was used as well as
* the last usage time. The ticket usage count is also incremented.
* <p>Tickets themselves are solely responsible to maintain their state. The
* determination of ticket usage is left up to the implementation and
* the specific ticket type.
*
* @see ExpirationPolicy
* @since 5.0.0
*/
void update();
}
package org.maxkey.authz.cas.endpoint.ticket.proxy;
import org.maxkey.authz.cas.endpoint.ticket.ExpirationPolicy;
import org.maxkey.authz.cas.endpoint.ticket.Service;
import org.maxkey.authz.cas.endpoint.ticket.TicketGrantingTicket;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
/**
* Interface for a proxy granting ticket. A proxy-granting ticket is an opaque string that is
* used by a service to obtain proxy tickets for obtaining access to a back-end service on behalf of a client.
* Proxy-granting tickets are obtained from CAS upon validation of a service ticket or a proxy ticket.
*
* @author Misagh Moayyed
* @since 4.2
*/
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
public interface ProxyGrantingTicket extends TicketGrantingTicket {
/** The prefix to use when generating an id for a Proxy Granting Ticket. */
String PROXY_GRANTING_TICKET_PREFIX = "PGT";
/** The prefix to use when generating an id for a Proxy Granting Ticket IOU. */
String PROXY_GRANTING_TICKET_IOU_PREFIX = "PGTIOU";
/**
* Grant a proxy ticket for a specific service.
*
* @param id The unique identifier for this ticket.
* @param service The service for which we are granting a ticket
* @param expirationPolicy the expiration policy.
* @param onlyTrackMostRecentSession track the most recent session by keeping the latest service ticket
* @return the service ticket granted to a specific service for the
* principal of the TicketGrantingTicket
*/
ProxyTicket grantProxyTicket(String id, Service service,
ExpirationPolicy expirationPolicy,
boolean onlyTrackMostRecentSession);
}
package org.maxkey.authz.cas.endpoint.ticket.proxy;
import org.maxkey.authz.cas.endpoint.ticket.ServiceTicket;
/**
* The {@link ProxyTicket} represents a CAS proxy ticket. A proxy ticket is an opaque string that a
* service uses as a credential to obtain access to a back-end service on behalf of a client.
* Proxy tickets are obtained from CAS upon a service’s
* presentation of a valid {@link ProxyGrantingTicket}
* and a service identifier for the back-end service to which it is connecting.
*
* @author Misagh Moayyed
* @since 4.2
*/
public interface ProxyTicket extends ServiceTicket {
/** Proxy ticket prefix applied to unique ids. */
String PROXY_TICKET_PREFIX = "PT";
}
......@@ -46,9 +46,9 @@ public abstract class RandomServiceTicketServices implements TicketServices {
ticketId = generator.getNewTicketId(CasConstants.PREFIX.SERVICE_TICKET_PREFIX);
}else if(ticket.getClass().getSimpleName().equalsIgnoreCase("ProxyTicketImpl")){
ticketId = generator.getNewTicketId(CasConstants.PREFIX.PROXY_TICKET_PREFIX);
}else if(ticket.getClass().getSimpleName().equalsIgnoreCase("ProxyTicketImpl")){
ticketId = generator.getNewTicketId(CasConstants.PREFIX.PROXY_TICKET_PREFIX);
}else if(ticket.getClass().getSimpleName().equalsIgnoreCase("ProxyTicketImpl")){
}else if(ticket.getClass().getSimpleName().equalsIgnoreCase("TicketGrantingTicketImpl")){
ticketId = generator.getNewTicketId(CasConstants.PREFIX.TICKET_GRANTING_TICKET_PREFIX);
}else {
ticketId = generator.getNewTicketId(CasConstants.PREFIX.PROXY_TICKET_PREFIX);
}
store(ticketId, ticket);
......
......@@ -28,7 +28,7 @@ public class RedisTicketServices extends RandomServiceTicketServices {
RedisConnectionFactory connectionFactory;
public static String PREFIX="REDIS_CAS_SERVICE_TICKET_";
public static String PREFIX="REDIS_CAS_TICKET_";
/**
* @param connectionFactory
*/
......
package org.maxkey.web.authorize.endpoint;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import javax.net.ssl.HttpsURLConnection;
public class CasRestClient {
public static void main(String... args) throws Exception
{
String username ="admin";
String password ="maxkey";
validateFromCAS(username,password);
}
public static boolean validateFromCAS(String username, String password) throws Exception
{
String url = "https://sso.maxkey.top/maxkey/authz/cas/v1/tickets";
try
{
org.maxkey.client.utils.HttpsTrusts.beforeConnection();
HttpsURLConnection hsu = (HttpsURLConnection)openConn(url);
String s = URLEncoder.encode("username","UTF-8") + "=" + URLEncoder.encode(username,"UTF-8");
s+="&" +URLEncoder.encode("password","UTF-8") + "=" + URLEncoder.encode(password,"UTF-8");
System.out.println(s);
OutputStreamWriter out = new OutputStreamWriter(hsu.getOutputStream());
BufferedWriter bwr = new BufferedWriter(out);
bwr.write(s);
bwr.flush();
bwr.close();
out.close();
String tgt = hsu.getHeaderField("location");
System.out.println( hsu.getResponseCode());
if(tgt != null && hsu.getResponseCode() == 201)
{
System.out.println(tgt);
System.out.println("Tgt is : " + tgt.substring( tgt.lastIndexOf("/") +1));
tgt = tgt.substring( tgt.lastIndexOf("/") +1);
bwr.close();
closeConn(hsu);
String serviceURL = "http://cas.demo.maxkey.top:8080/demo-cas/";
String encodedServiceURL = URLEncoder.encode("service","utf-8") +"=" + URLEncoder.encode(serviceURL,"utf-8");
System.out.println("Service url is : " + encodedServiceURL);
String myURL = url+ "/"+ tgt ;
System.out.println(myURL);
hsu = (HttpsURLConnection)openConn(myURL);
out = new OutputStreamWriter(hsu.getOutputStream());
bwr = new BufferedWriter(out);
bwr.write(encodedServiceURL);
bwr.flush();
bwr.close();
out.close();
System.out.println("Response code is: " + hsu.getResponseCode());
BufferedReader isr = new BufferedReader( new InputStreamReader(hsu.getInputStream()));
String line;
System.out.println( hsu.getResponseCode());
while ((line = isr.readLine()) != null) {
System.out.println( line);
}
isr.close();
hsu.disconnect();
return true;
}
else
{
return false;
}
}
catch(MalformedURLException mue)
{
mue.printStackTrace();
throw mue;
}
catch(IOException ioe)
{
ioe.printStackTrace();
throw ioe;
}
}
static URLConnection openConn(String urlk) throws MalformedURLException, IOException
{
URL url = new URL(urlk);
HttpsURLConnection hsu = (HttpsURLConnection) url.openConnection();
hsu.setDoInput(true);
hsu.setDoOutput(true);
hsu.setRequestMethod("POST");
return hsu;
}
static void closeConn(HttpsURLConnection c)
{
c.disconnect();
}
}
package org.maxkey.web.authorize.endpoint;
/*
import org.pac4j.cas.profile.CasRestProfile;
import org.pac4j.cas.client.rest.CasRestFormClient;
import org.pac4j.cas.config.CasConfiguration;
import org.pac4j.cas.credentials.authenticator.CasRestAuthenticator;
import org.pac4j.cas.profile.CasProfile;
import org.pac4j.core.context.JEEContext;
import org.pac4j.core.context.WebContext;
import org.pac4j.core.credentials.TokenCredentials;
import org.pac4j.core.credentials.UsernamePasswordCredentials;
import org.pac4j.core.exception.HttpAction;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import java.util.Map;
import java.util.Set;
public class RestTestClient {
public static void main(String[] args ) throws HttpAction {
final String casUrlPrefix = "http://localhost:8080/cas";
String username = args[0];
String password = args[1];
String serviceUrl = args[2];
CasConfiguration casConfiguration = new CasConfiguration(casUrlPrefix);
final CasRestAuthenticator authenticator = new CasRestAuthenticator(casConfiguration);
final CasRestFormClient client = new CasRestFormClient(casConfiguration,"username","password");
final MockHttpServletRequest request = new MockHttpServletRequest();
final MockHttpServletResponse response = new MockHttpServletResponse();
final WebContext webContext = new JEEContext(request, response);
casConfiguration.init(webContext);
UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(username,password,"testclient");
CasRestAuthenticator restAuthenticator = new CasRestAuthenticator(casConfiguration);
// authenticate with credentials (validate credentials)
restAuthenticator.validate(credentials, webContext);
final CasRestProfile profile = (CasRestProfile) credentials.getUserProfile();
// get service ticket
final TokenCredentials casCredentials = client.requestServiceTicket(serviceUrl, profile, webContext);
// validate service ticket
final CasProfile casProfile = client.validateServiceTicket(serviceUrl, casCredentials, webContext);
Map<String,Object> attributes = casProfile.getAttributes();
Set<Map.Entry<String,Object>> mapEntries = attributes.entrySet();
for (Map.Entry entry : mapEntries) {
System.out.println(entry.getKey() + ":" + entry.getValue());
}
client.destroyTicketGrantingTicket(profile,webContext);
}
}*/
......@@ -112,6 +112,9 @@ public class MaxKeyMvcConfig implements WebMvcConfigurer {
//cas3.0 Validate
.excludePathPatterns("/authz/cas/p3/serviceValidate")
.excludePathPatterns("/authz/cas/p3/proxyValidate")
//rest
.excludePathPatterns("/authz/cas/v1/tickets")
.excludePathPatterns("/authz/cas/v1/tickets/*")
//OAuth
.addPathPatterns("/oauth/v20/authorize")
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册