單點登入CAS6-服務端自定義返回的使用者資訊
原理
返回的使用者資訊是在deployerConfigContext.xml
中的配置的
既然想自定義返回的使用者資訊,那麼繼承org.jasig.services.persondir.support.StubPersonAttributeDao就好了
1、建立com.jadyer.sso.authentication extends StubPersonAttributeDao並複寫getPerson()方法
使用@Component(value=”attributeRepository”)定義它的BeanID
2、註釋deployerConfigContext.xml
中的<bean
和
id="attributeRepository"><util:map
配置
id="attrRepoBackingMap">
3、修改WEB-INFviewjspprotocol2.0casServiceValidationSuccess.jsp
(不要改3.0下面的)
具體改動,詳見下方貼出的程式碼
另外:返回給客戶端的相關資訊是由org.jasig.services.persondir.IPersonAttributeDao介面定義的
StubPersonAttributeDao就是IPersonAttributeDao的實現之一
其它實現如SingleRowJdbcPersonAttributeDao、LdapPersonAttributeDao等
所以也可在deployerConfigContext.xml中配置的實現為SingleRowJdbcPersonAttributeDao
也就是<bean id="attributeRepository"
class="org.jasig...persondir.support.jdbc.SingleRowJdbcPersonAttributeDao">
不過,個人覺得這樣不是很靈活,所以就不貼示例程式碼了
程式碼
下面是自定義的控制返回的使用者資訊的UserStubPersonAttributeDao.java
package com.jadyer.sso.authentication;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import org.jasig.services.persondir.IPersonAttributes;
import org.jasig.services.persondir.support.AttributeNamedPersonImpl;
import org.jasig.services.persondir.support.StubPersonAttributeDao;
import org.springframework.stereotype.Component;
import com.jadyer.sso.model.User;
/**
* 自定義的返回給客戶端相關資訊
* Created by 玄玉<https://jadyer.github.io/> on 2015/07/18 17:52.
*/
@Component(value="attributeRepository")
public class UserStubPersonAttributeDao extends StubPersonAttributeDao {
@Resource
private UserDaoJdbc userDaoJdbc;
@Override
public IPersonAttributes getPerson(String uid) {
Map<String, List<Object>> attributes = new HashMap<String, List<Object>>();
try {
User user = userDaoJdbc.getByUsername(uid);
attributes.put("userId", Collections.singletonList((Object)user.getUsercode()));
attributes.put("username", Collections.singletonList((Object)user.getUsername()));
attributes.put("usernamePlain", Collections.singletonList((Object)URLEncoder.encode(user.getUsernamePlain(), "UTF-8")));
attributes.put("blogURL", Collections.singletonList((Object)"https://jadyer.github.io/"));
attributes.put("blogger", Collections.singletonList((Object)URLEncoder.encode("玄玉", "UTF-8")));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return new AttributeNamedPersonImpl(attributes);
}
}
下面是用到的查詢資料庫的UserDaoJdbc.java
package com.jadyer.sso.authentication;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.annotation.Resource;
import javax.sql.DataSource;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import com.jadyer.sso.model.User;
@Repository
public class UserDaoJdbc {
private static final String SQL_USER_VERIFY = "SELECT COUNT(*) FROM permission_operator WHERE operator_login=? AND operator_pwd=SHA1(?)";
private static final String SQL_USER_GET = "SELECT * FROM permission_operator WHERE operator_login=?";
private JdbcTemplate jdbcTemplate;
@Resource
public void setDataSource(DataSource dataSource){
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
public boolean verifyAccount(String username, String password){
try{
//驗證使用者名稱和密碼是否正確
return 1==this.jdbcTemplate.queryForObject(SQL_USER_VERIFY, new Object[]{username, password}, Integer.class);
}catch(EmptyResultDataAccessException e){
return false;
}
}
public User getByUsername(String username){
try{
//根據使用者名稱獲取使用者資訊
return (User)this.jdbcTemplate.queryForObject(SQL_USER_GET, new Object[]{username}, new UserRowMapper());
}catch(EmptyResultDataAccessException e){
return new User();
}
}
}
class UserRowMapper implements RowMapper<User> {
@Override
public User mapRow(ResultSet rs, int index) throws SQLException {
User user = new User();
user.setUsercode(rs.getString("operator_code"));
user.setUsername(rs.getString("operator_login"));
user.setUsernamePlain(rs.getString("operator_name"));
return user;
}
}
下面是用到的User.java
package com.jadyer.sso.model;
public class User {
private String usercode;
private String username;
private String usernamePlain;
/*-- setter和getter略 --*/
}
下面是deployerConfigContext.xml
的修改部分
<!-- 註釋掉預設的attributeRepository實現,採用自定義的UserStubPersonAttributeDao -->
<!--
<bean id="attributeRepository" class="org.jasig.services.persondir.support.StubPersonAttributeDao"
p:backingMap-ref="attrRepoBackingMap" />
<util:map id="attrRepoBackingMap">
<entry key="uid" value="uid" />
<entry key="eduPersonAffiliation" value="eduPersonAffiliation" />
<entry key="groupMembership" value="groupMembership" />
</util:map>
-->
下面是WEB-INFviewjspprotocol2.0casServiceValidationSuccess.jsp
<%--
Licensed to Jasig under one or more contributor license
agreements. See the NOTICE file distributed with this work
for additional information regarding copyright ownership.
Jasig licenses this file to you 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 the following location:
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.
--%>
<%@ page session="false" contentType="application/xml; charset=UTF-8" %>
<%@ 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.primaryAuthentication.principal.id)}</cas:user>
<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>
<!--
新增部分如下:CASServer驗證成功後,該頁面負責生成與客戶端互動的XML資訊
預設的casServiceValidationSuccess.jsp中只包括使用者名稱,並不提供其他的屬性資訊,因此需要對該頁面進行擴充套件
-->
<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>
</cas:authenticationSuccess>
</cas:serviceResponse>
最後是客戶端獲取服務端返回的自定義使用者資訊的index.jsp
<%@ page pageEncoding="UTF-8"%>
<%@ page import="java.util.Map"%>
<%@ page import="java.net.URLDecoder"%>
<%@ page import="org.jasig.cas.client.util.AssertionHolder"%>
<%@ page import="org.jasig.cas.client.authentication.AttributePrincipal"%>
<body style="background-color:#CBE0C9;">
<span style="color:red; font-size:32px; font-weight:bold;">客戶端登入成功</span>
</body>
<hr size="2">
<%
AttributePrincipal principal = (AttributePrincipal)request.getUserPrincipal();
Map<String, Object> attributes = principal.getAttributes();
out.print("principal.getName()=" + principal.getName() + "<br/>");
out.print("request.getRemoteUser()=" + request.getRemoteUser() + "<br/>");
out.print("登入使用者:" + attributes.get("userId") + "<br/>");
out.print("登入時間:" + AssertionHolder.getAssertion().getAuthenticationDate() + "<br/>");
out.print("-----------------------------------------------------------------------<br/>");
for(Map.Entry<String, Object> entry : attributes.entrySet()){
//服務端返回中文時需要encode,客戶端接收顯示中文時需要decode,否則會亂碼
out.print(entry.getKey() + "=" + URLDecoder.decode(entry.getValue().toString(), "UTF-8") + "<br/>");
}
out.print("-----------------------------------------------------------------------<br/>");
Map<String, Object> attributes22 = AssertionHolder.getAssertion().getAttributes();
for(Map.Entry<String, Object> entry : attributes22.entrySet()){
out.print(entry.getKey() + "=" + entry.getValue() + "<br/>");
}
out.print("-----------------------------------------------------------------------<br/>");
Map<String, Object> attributes33 = AssertionHolder.getAssertion().getPrincipal().getAttributes();
for(Map.Entry<String, Object> entry : attributes33.entrySet()){
out.print(entry.getKey() + "=" + entry.getValue() + "<br/>");
}
%>
效果圖
關於客戶端如何配置(包括通過spring),詳見本系列的下一篇博文
(今天頭疼還發燒,明天再發客戶端的配置方法)
相關文章
- 改造CAS單點登入 --- 自定義登陸頁面(客戶端)客戶端
- CAS SSO單點登入服務端環境搭建服務端
- [精華][推薦]CAS SSO單點登入服務端客戶端例項服務端客戶端
- wordpress 自定義登入表單
- 2.CAS SSO單點登入服務端環境搭建原始碼服務端原始碼
- CAS SSO單點登入服務端環境搭建之框架深度分析服務端框架
- .關於CAS SSO單點登入服務端環境搭建原始碼分析服務端原始碼
- 2.關於CAS SSO單點登入服務端環境搭建原始碼服務端原始碼
- 基於CAS的WEB單點登入(sso)服務端及其tomcat/nginx https配置Web服務端TomcatNginxHTTP
- 2.關於CAS SSO單點登入服務端環境搭建原始碼分析服務端原始碼
- linux SSH服務允許root使用者遠端登入Linux
- Laravel 中自定義使用者登入的資料表Laravel
- anaular中的自定義服務
- OAuth2.0協議入門(三):OAuth2.0授權與單點登入(SSO)的區別以及單點登入服務端從設計到實現OAuth協議服務端
- 2.基於CAS SSO單點登入服務端環境搭建+架構原始碼服務端架構原始碼
- Spring Cloud企業架構之CAS SSO單點登入服務端環境搭建SpringCloud架構服務端
- Spring Cloud 企業架構之CAS SSO單點登入服務端環境搭建SpringCloud架構服務端
- Spring Cloud 企業架構之CAS SSO單點登入服務端環境搭建SpringCloud架構服務端
- Spring Cloud 企業架構之CAS SSO單點登入服務端環境搭建SpringCloud架構服務端
- 2.基於CAS SSO單點登入服務端環境搭建架構原始碼服務端架構原始碼
- Ubuntu開啟ssh服務遠端登入Ubuntu
- Laravel5.6 實現後臺管理登入(自定義使用者表登入)Laravel
- 2.CAS SSO單點登入服務端環境搭建之原始碼詳細解說服務端原始碼
- Java版分散式微服務雲開發架構之CAS SSO單點登入服務端環境搭建Java分散式微服務架構服務端
- java版Spring Cloud 企業架構之CAS SSO單點登入服務端環境搭建JavaSpringCloud架構服務端
- CentOS7自定義服務CentOS
- Spring Cloud + Spring Boot企業架構之CAS SSO單點登入服務端環境搭建CloudSpring Boot架構服務端
- SpringCloud大型企業分散式微服務雲架構原始碼+CAS SSO單點登入服務端環境搭建SpringGCCloud分散式微服務架構原始碼服務端
- CAS自定義登入驗證方法
- 自定義登入和登出頁面
- Vue 3深度探索:自定義渲染器與服務端渲染Vue服務端
- Asp.Net Core入門之自定義服務註冊ASP.NET
- 建站篇-使用者認證系統-自定義登入系統
- 單點登入原理
- spring security 之自定義表單登入原始碼跟蹤Spring原始碼
- CAS SSO單點登入服務端環境搭建解析之Spring Cloud + Spring Boot企業架構服務端CloudSpring Boot架構
- Spring Cloud + Spring Boot + Mybatis 企業架構之CAS SSO單點登入服務端環境搭建CloudSpring BootMyBatis架構服務端
- Spring Cloud + Spring Boot + Mybatis 企業架構之CAS SSO單點登入服務端環境搭建CloudSpring BootMyBatis架構服務端