CAS 单点登录4.24版本 登录调用其它系统并且返回客户端用其它的用户信息改造
1.登录调用其它系统。修改deployerConfigContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:sec="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<!-- 引入配置文件 -->
<!-- <bean id="propertyConfigurer" -->
<!-- class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> -->
<!-- <property name="location" value="classpath:redis.properties" /> -->
<!-- </bean> -->
<util:map id="authenticationHandlersResolvers">
<entry key-ref="proxyAuthenticationHandler" value-ref="proxyPrincipalResolver" />
<entry key-ref="primaryAuthenticationHandler" value-ref="primaryPrincipalResolver" />
</util:map>
<util:list id="authenticationMetadataPopulators">
<ref bean="successfulHandlerMetaDataPopulator" />
<ref bean="rememberMeAuthenticationMetaDataPopulator" />
</util:list>
<!-- <alias name="acceptUsersAuthenticationHandler" alias="primaryAuthenticationHandler" /> -->
<!--begin 从数据库中的用户表中读取 -->
<bean id="callIntefaceAuthenticationHandler" name="primaryAuthenticationHandler" class="com.hivecas.adaptors.CallIntefaceAuthenticationHandler">
</bean>
<alias name="userInfoPrincipalResolver" alias="primaryPrincipalResolver" />
<!-- <alias name="personDirectoryPrincipalResolver" alias="primaryPrincipalResolver" /> -->
<bean id="attributeRepository" class="org.jasig.services.persondir.support.NamedStubPersonAttributeDao"
p:backingMap-ref="attrRepoBackingMap" />
<util:map id="attrRepoBackingMap">
<entry key="uid" value="uid" />
<entry key="eduPersonAffiliation" value="eduPersonAffiliation" />
<entry key="groupMembership" value="groupMembership" />
<entry>
<key><value>memberOf</value></key>
<list>
<value>faculty</value>
<value>staff</value>
<value>org</value>
</list>
</entry>
</util:map>
<!--end 从数据库中的用户表中读取 -->
<alias name="serviceThemeResolver" alias="themeResolver" />
<alias name="jsonServiceRegistryDao" alias="serviceRegistryDao" />
<!-- <alias name="defaultTicketRegistry" alias="ticketRegistry" /> -->
<!-- 票据保存方式及有效期设置 -->
<alias name="redisTicketRegistry" alias="ticketRegistry" />
<!-- <bean id="redisTicketRegistry" class="com.hivescm.cas.ticket.registry.RedisTicketRegistry" -->
<!-- p:client-ref="ticketRedisTemplate" -->
<!-- p:tgtTimeout="28800" -->
<!-- p:stTimeout="10"/> -->
<bean id="redisTicketRegistry" class="com.hivescm.cas.ticket.registry.RedisClusterTicketRegistry"
p:client-ref="redisTemplate"
p:tgtTimeout="28800"
p:stTimeout="1000"/>
<!-- redis连接池 -->
<!-- jedis 配置 -->
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig" >
<!-- 最大空闲数 -->
<property name="maxIdle" value="${redis.maxIdle}" />
<!-- 最大建立连接等待时间 -->
<property name="maxWaitMillis" value="${redis.maxWait}" />
<!-- 是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个 -->
<property name="testOnBorrow" value="${redis.testOnBorrow}" />
</bean >
<!-- 配置文件加载 -->
<bean id="resourcePropertySource" class="org.springframework.core.io.support.ResourcePropertySource">
<constructor-arg name="name" value="redis.cluster.properties"/>
<constructor-arg name="resource" value="classpath:redis.cluster.properties"/>
</bean>
<!-- redisCluster配置 -->
<bean id="redisClusterConfiguration" class="org.springframework.data.redis.connection.RedisClusterConfiguration">
<constructor-arg name="propertySource" ref="resourcePropertySource"/>
</bean>
<!-- redis服务器中心 -->
<bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" >
<constructor-arg name="clusterConfig" ref="redisClusterConfiguration"/>
<constructor-arg name="poolConfig" ref="poolConfig"/>
<property name="password" value="${redis.password}" />
<property name="timeout" value="${redis.timeout}" ></property>
</bean >
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate" >
<property name="connectionFactory" ref="connectionFactory" />
<!-- 如果不配置Serializer,那么存储的时候缺省使用String,如果用User类型存储,那么会提示错误User can't cast to String!! -->
<property name="keySerializer" >
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
</property>
<property name="valueSerializer" >
<bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" />
</property>
<property name="hashKeySerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
</property>
<property name="hashValueSerializer">
<bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
</property>
</bean >
<alias name="ticketGrantingTicketExpirationPolicy" alias="grantingTicketExpirationPolicy" />
<!-- <alias name="multiTimeUseOrTimeoutExpirationPolicy" alias="serviceTicketExpirationPolicy" /> -->
<alias name="neverExpiresExpirationPolicy" alias="serviceTicketExpirationPolicy" />
<alias name="anyAuthenticationPolicy" alias="authenticationPolicy" />
<alias name="acceptAnyAuthenticationPolicyFactory" alias="authenticationPolicyFactory" />
<bean id="auditTrailManager"
class="org.jasig.inspektr.audit.support.Slf4jLoggingAuditTrailManager"
p:entrySeparator="${cas.audit.singleline.separator:|}"
p:useSingleLine="${cas.audit.singleline:false}"/>
<alias name="neverThrottle" alias="authenticationThrottle" />
<util:list id="monitorsList">
<ref bean="memoryMonitor" />
<ref bean="sessionMonitor" />
</util:list>
<alias name="defaultPrincipalFactory" alias="principalFactory" />
<alias name="defaultAuthenticationTransactionManager" alias="authenticationTransactionManager" />
<alias name="defaultPrincipalElectionStrategy" alias="principalElectionStrategy" />
<alias name="tgcCipherExecutor" alias="defaultCookieCipherExecutor" />
</beans>
2.CallIntefaceAuthenticationHandler
package com.hivecas.adaptors;
import org.apache.commons.lang3.StringUtils;
import org.jasig.cas.authentication.HandlerResult;
import org.jasig.cas.authentication.PreventedException;
import org.jasig.cas.authentication.UsernamePasswordCredential;
import org.jasig.cas.authentication.handler.support.AbstractUsernamePasswordAuthenticationHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.IncorrectResultSizeDataAccessException;
import org.springframework.stereotype.Component;
import com.alibaba.fastjson.JSONObject;
import com.hivecas.model.UsernamePasswordStrongCredential;
import com.hivecas.util.HttpUtil;
import com.hivescm.common.domain.DataResult;
import javax.security.auth.login.AccountNotFoundException;
import javax.security.auth.login.FailedLoginException;
import javax.validation.constraints.NotNull;
import java.security.GeneralSecurityException;
import java.util.HashMap;
import java.util.Map;
/**
* 自定义请求接口验证用户登录权限
* @author lvxt
*
*/
@Component("callIntefaceAuthenticationHandler")
public class CallIntefaceAuthenticationHandler extends AbstractUsernamePasswordAuthenticationHandler {
@NotNull
private String requestUrl;
@Override
protected final HandlerResult authenticateUsernamePasswordInternal(final UsernamePasswordCredential credential)
throws GeneralSecurityException, PreventedException {
if (StringUtils.isBlank(requestUrl)) {
throw new GeneralSecurityException("Authentication handler is not configured correctly");
}
final String username = credential.getUsername();
final String password = credential.getPassword();
Map dataMap;
UsernamePasswordStrongCredential strongCredential;
try {
Map map =new HashMap();
map.put("loginName", username);
map.put("password", password);
String resultJsonStr=HttpUtil.postRequest(requestUrl, map);
DataResult data= (DataResult) JSONObject.parseObject(resultJsonStr, DataResult.class);
if (!data.isSuccess()) {
throw new FailedLoginException("Password does not match value on record.");
}
strongCredential=(UsernamePasswordStrongCredential) credential;
dataMap=(Map) data.getResult();
strongCredential.setAttributes(dataMap);
} catch (final IncorrectResultSizeDataAccessException e) {
if (e.getActualSize() == 0) {
throw new AccountNotFoundException(username + " not found with SQL query");
} else {
throw new FailedLoginException("Multiple records found for " + username);
}
} catch (final DataAccessException e) {
throw new PreventedException("SQL exception while executing query for " + username, e);
}
return createHandlerResult(strongCredential, this.principalFactory.createPrincipal(username,dataMap), null);
}
public String getRequestUrl() {
return requestUrl;
}
@Autowired
public void setRequestUrl(@Value("${cas.login.auth.request.url:}") String requestUrl) {
this.requestUrl = requestUrl;
}
}
3.UsernamePasswordStrongCredential的改造,用于存入调用登录接口返回的用户信息存入map中
package com.hivecas.model;
import java.util.HashMap;
import java.util.Map;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.jasig.cas.authentication.UsernamePasswordCredential;
public class UsernamePasswordStrongCredential extends UsernamePasswordCredential {
/**
* 带验证码的登录界面
*/
private static final long serialVersionUID = 1L;
/** 验证码*/
@Size(min = 1, message = "required.authcode")
private String authcode;
/**登录类型
* 1.pc登录 2 移动端登录
*/
@NotNull
@Size(min = 1, message = "required.loginType")
private String loginType;
/**
* 用户返回数据
*/
private Map<String,Object> attributes = new HashMap<>();
public Map<String, Object> getAttributes() {
return attributes;
}
public void setAttributes(Map<String, Object> attributes) {
this.attributes = attributes;
}
public String getLoginType() {
return loginType;
}
public void setLoginType(String loginType) {
this.loginType = loginType;
}
/**
*
* @return
*/
public final String getAuthcode() {
return authcode;
}
/**
*
* @param authcode
*/
public final void setAuthcode(String authcode) {
this.authcode = authcode;
}
public UsernamePasswordStrongCredential() {
super();
}
public UsernamePasswordStrongCredential(String userName,
String password) {
super(userName, password);
}
public UsernamePasswordStrongCredential(String userName,
String password,String loginType) {
super(userName, password);
setLoginType(loginType);
}
@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
final UsernamePasswordStrongCredential that = (UsernamePasswordStrongCredential) o;
if (getPassword() != null ? !getPassword().equals(that.getPassword())
: that.getPassword() != null) {
return false;
}
if (getPassword() != null ? !getPassword().equals(that.getPassword())
: that.getPassword() != null) {
return false;
}
if (authcode != null ? !authcode.equals(that.getAuthcode())
: that.getAuthcode() != null)
return false;
return true;
}
@Override
public int hashCode() {
return new HashCodeBuilder().append(getUsername())
.append(getPassword()).append(authcode).toHashCode();
}
}
4.UserInfoPrincipalResolver.java
package org.jasig.cas.authentication.principal;
import javax.validation.constraints.NotNull;
import org.jasig.cas.authentication.Credential;
import org.jasig.cas.authentication.principal.DefaultPrincipalFactory;
import org.jasig.cas.authentication.principal.Principal;
import org.jasig.cas.authentication.principal.PrincipalFactory;
import org.jasig.cas.authentication.principal.PrincipalResolver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import com.hivecas.model.UsernamePasswordStrongCredential;
@Component("userInfoPrincipalResolver")
public class UserInfoPrincipalResolver implements PrincipalResolver{
protected final transient Logger logger = LoggerFactory.getLogger(this.getClass());
/**
* Factory to create the principal type.
**/
@NotNull
protected PrincipalFactory principalFactory = new DefaultPrincipalFactory();
@Override
public Principal resolve(Credential credential) {
logger.debug("Attempting to resolve a principal...");
final String principalId = extractPrincipalId(credential);
UsernamePasswordStrongCredential strongCredential=(UsernamePasswordStrongCredential) credential;
return this.principalFactory.createPrincipal(principalId, strongCredential.getAttributes());
}
@Override
public boolean supports(Credential credential) {
return credential != null && credential.getId() != null;
}
/**
* Extracts the id of the user from the provided credential. This method should be overridden by subclasses to
* achieve more sophisticated strategies for producing a principal ID from a credential.
*
* @param credential the credential provided by the user.
* @return the username, or null if it could not be resolved.
*/
protected String extractPrincipalId(final Credential credential) {
return credential.getId();
}
}
5.页面2.0文件下的casServiceValidationSuccess.jsp改造
<%@ page session="false" contentType="application/xml; charset=UTF-8" %>
<%@ page import="java.util.*, java.util.Map.Entry" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
<cas:authenticationSuccess>
<cas:user>${fn:escapeXml(assertion.chainedAuthentications[fn:length(assertion.chainedAuthentications)-1].principal.id)}</cas:user>
<c:if test="${fn:length(assertion.chainedAuthentications[fn:length(assertion.chainedAuthentications)-1].principal.attributes)> 0}">
<cas:attributes>
<c:forEach var="attr" items="${assertion.chainedAuthentications[fn:length(assertion.chainedAuthentications)-1].principal.attributes}">
<cas:${fn:escapeXml(attr.key)}>${fn:escapeXml(attr.value)}</cas:${fn:escapeXml(attr.key)}>
</c:forEach>
</cas:attributes>
</c:if>
<c:if test="${not empty pgtIou}">
<cas:proxyGrantingTicket>${pgtIou}</cas:proxyGrantingTicket>
</c:if>
<c:if test="${fn:length(assertion.chainedAuthentications) > 1}">
<cas:proxies>
<c:forEach var="proxy" items="${assertion.chainedAuthentications}" varStatus="loopStatus" begin="0" end="${fn:length(assertion.chainedAuthentications)-2}" step="1">
<cas:proxy>${fn:escapeXml(proxy.principal.id)}</cas:proxy>
</c:forEach>
</cas:proxies>
</c:if>
</cas:authenticationSuccess>
</cas:serviceResponse>
6.客户端测试页面index.jsp的取值效果
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="org.jasig.cas.client.authentication.AttributePrincipal" %>
<%@ page import="java.util.Map" %>
<%@ page import="java.lang.String" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>首页</title>
</head>
<body>
<div style="padding-left: 30%">
用户名: <%=request.getAttribute("name")%>
<h1>订单系统<%=request.getLocalPort() %></h1>
<% Cookie[] array =request.getCookies();
String JSESSIONID="";
if(array!=null)
for(Cookie ck:array)
{
String ckName=ck.getName();
if(ckName.equals("JSESSIONID"))
{
JSESSIONID=ck.getValue();
}
}
%>
<%
request.setCharacterEncoding("UTF-8");
AttributePrincipal principal = (AttributePrincipal) request.getUserPrincipal();
Map attributes = principal.getAttributes();
String id=(String)attributes.get("id");
String phone=(String)attributes.get("phone");
String email=(String)attributes.get("email");
%>
Cookie中的JSESSIONID=<%=JSESSIONID%><br>
用户id=<%=id%><br>
用户手机号=<%=phone%><br>
用户email=<%=email%><br>
<br><br>
<a href="http://passport.hivescm.com/cas/logout" >退出</a>
</div>
</body>
</html>

浙公网安备 33010602011771号