CAS之5.2x版本自定義返回訊息-yellowcong
阿新 • • 發佈:2019-02-15
單點登入,預設是隻返回登入的使用者名稱,不會返回其他的資訊,我們需要在這個基礎上進行擴充套件,開發。配置自定義返回訊息的時候,需要自定義表單處理,然後根據獲取的結果來返回自定義資料。這種需求的應用場景就是,A系統登入,我想返回啥,B系統登入,我又想返回啥。這個就需要自定義了,而且還有預設系統返回的只有使用者名稱,這個訊息太少,兄弟們不得不進行擴充套件操作。擴充套件步驟:1、修改services資料夾的json配置,2、配置自定義認證類,並配置到springboot中。
專案地址
#客戶端地址
https://gitee.com/yellowcong/springboot_cas/tree/master/cas -client-maven
#伺服器端地址
https://gitee.com/yellowcong/springboot_cas/tree/master/cas-server-result
目錄結構
服務端,主要是修改了services裡面的子站點配置資訊的返回策略,然後修改了自定義驗證器裡面的返回值。再次強調,伺服器端和客戶端的證書必須一致,不然會拋異常,說證書有問題
1、修改services配置
預設配置
配置HTTPSandIMAPS-10000001.json 檔案,這個是cas預設的配置,如果我們的請求沒有專門的配置,就會找這個配置了,這個配置^(http|https|imaps)://.*
,表示我這個地方是啥客戶端都接的,所以沒問題啊,最好開發中,別這麼搞,根據自己的域名來定義規則
{
"@class" : "org.apereo.cas.services.RegexRegisteredService",
"serviceId" : "^(http|https|imaps)://.*",
"name" : "HTTPS and IMAPS",
"id" : 10000001,
"description" : "This service definition authorizes all application urls that support HTTPS and IMAPS protocols.",
"evaluationOrder" : 10000,
"attributeReleasePolicy " : {
"@class" : "org.apereo.cas.services.ReturnAllAttributeReleasePolicy"
}
}
對於某個站點配置
只有yellowcong.xx 的網站訪問這個資料的時候,就會跳到這個模版
{
"@class" : "org.apereo.cas.services.RegexRegisteredService",
"serviceId" : "^(https|imaps|http)://yellowcong.*",
"name" : "BaiDu",
"id" : 10000002,
"description" : "This service definition authorizes all application urls that supportBaiDu.",
"evaluationOrder" : 1,
"theme": "demo",
"attributeReleasePolicy" : {
"@class" : "org.apereo.cas.services.ReturnAllAttributeReleasePolicy"
}
}
限制某些欄位反回
"attributeReleasePolicy" : { "@class" : "org.apereo.cas.services.ReturnAllowedAttributeReleasePolicy", "allowedAttributes" : [ "java.util.ArrayList", [ "school", "email" ] ]
}
服務端驗證器修改
驗證器,獲取了資料庫的資料後,存放到Map集合裡面,然後返回結果到客戶端。
Map<String,Object> result = new HashMap<String,Object>();
result.put("username", rs.getString("username"));
result.put("password", rs.getString("password"));
result.put("email", rs.getString("email"));
result.put("addr", rs.getString("addr"));
result.put("phone", rs.getString("phone"));
result.put("age", rs.getString("age"));
//允許登入,並且通過this.principalFactory.createPrincipal來返回使用者屬性
return createHandlerResult(credential, this.principalFactory.createPrincipal(username, result), null);
下面是完整程式碼
package com.yellowcong.auth.handler;
import java.security.GeneralSecurityException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import javax.security.auth.login.AccountLockedException;
import javax.security.auth.login.FailedLoginException;
import org.apereo.cas.authentication.Credential;
import org.apereo.cas.authentication.HandlerResult;
import org.apereo.cas.authentication.PreventedException;
import org.apereo.cas.authentication.UsernamePasswordCredential;
import org.apereo.cas.authentication.exceptions.AccountDisabledException;
import org.apereo.cas.authentication.exceptions.InvalidLoginLocationException;
import org.apereo.cas.authentication.handler.support.AbstractPreAndPostProcessingAuthenticationHandler;
import org.apereo.cas.authentication.principal.PrincipalFactory;
import org.apereo.cas.services.ServicesManager;
/**
* @author yellowcong
* 建立日期:2018/02/02
*
*/
public class CustomerHandler extends AbstractPreAndPostProcessingAuthenticationHandler {
public CustomerHandler(String name, ServicesManager servicesManager, PrincipalFactory principalFactory,
Integer order) {
super(name, servicesManager, principalFactory, order);
}
/**
* 用於判斷使用者的Credential(換而言之,就是登入資訊),是否是俺能處理的
* 就是有可能是,子站點的登入資訊中不止有使用者名稱密碼等資訊,還有部門資訊的情況
*/
@Override
public boolean supports(Credential credential) {
//判斷傳遞過來的Credential 是否是自己能處理的型別
return credential instanceof UsernamePasswordCredential;
}
/**
* 用於授權處理
*/
@Override
protected HandlerResult doAuthentication(Credential credential) throws GeneralSecurityException, PreventedException {
UsernamePasswordCredential usernamePasswordCredentia = (UsernamePasswordCredential) credential;
//獲取傳遞過來的使用者名稱和密碼
String username = usernamePasswordCredentia.getUsername();
String password = usernamePasswordCredentia.getPassword();
Connection conn = null;
try {
Class.forName("com.mysql.jdbc.Driver");
//直接是原生的資料庫配置啊
String url = "jdbc:mysql://127.0.0.1:3306/yellowcong";
String user = "root";
String pass = "root";
conn = DriverManager.getConnection(url,user, pass);
//查詢語句
String sql = "SELECT * FROM cas_user WHERE username =? AND PASSWORD = ?";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, username);
ps.setString(2, password);
ResultSet rs = ps.executeQuery();
if(rs.next()) {
//存放資料到裡面
Map<String,Object> result = new HashMap<String,Object>();
result.put("username", rs.getString("username"));
result.put("password", rs.getString("password"));
result.put("email", rs.getString("email"));
result.put("addr", rs.getString("addr"));
result.put("phone", rs.getString("phone"));
result.put("age", rs.getString("age"));
//允許登入,並且通過this.principalFactory.createPrincipal來返回使用者屬性
return createHandlerResult(credential, this.principalFactory.createPrincipal(username, result), null);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
if(conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
//當是admin使用者的情況,直接就登入了,誰叫他是admin使用者呢
if(username.startsWith("admin")) {
//直接返回去了
return createHandlerResult(credential, this.principalFactory.createPrincipal(username, Collections.emptyMap()), null);
}else if (username.startsWith("lock")) {
//使用者鎖定
throw new AccountLockedException();
} else if (username.startsWith("disable")) {
//使用者禁用
throw new AccountDisabledException();
} else if (username.startsWith("invali")) {
//禁止登入該工作站登入
throw new InvalidLoginLocationException();
} else if (username.startsWith("passorwd")) {
//密碼錯誤
throw new FailedLoginException();
} else if (username.startsWith("account")) {
//賬號錯誤
throw new AccountLockedException();
}
return null;
}
}
客戶端獲取返回中,session的資料
客戶端獲取的資料,也是放在session裡面的,直接就可以通過獲取session中的_const_cas_assertion_
欄位獲取到返回的使用者登入的名稱資訊。通過request.getUserPrincipal(); 可以獲取到使用者的授權資訊,也就是使用者返回的欄位資訊。
//Object object =request.getSession().getAttribute("_const_cas_assertion_");
//Assertion assertion =(Assertion)object;
//獲取cas給我們傳遞回來的物件,這個東西放到了session中
//session的 key是 _const_cas_assertion_
Assertion assertion = (Assertion) request.getSession().getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION);
//獲取登入使用者名稱
String loginName =assertion.getPrincipal().getName();
System.out.printf("登入使用者名稱:%s\r\n",loginName);
//獲取自定義返回值的資料
Principal principal = (AttributePrincipal) request.getUserPrincipal();
if (request.getUserPrincipal() != null) {
if (principal instanceof AttributePrincipal) {
//cas傳遞過來的資料
Map<String,Object> result =( (AttributePrincipal)principal).getAttributes();
for(Map.Entry<String, Object> entry :result.entrySet()) {
String key = entry.getKey();
Object val = entry.getValue();
System.out.printf("%s:%s\r\n",key,val);
}
}
}
驗證
登入了資料庫的賬戶和密碼,然後,使用張三的使用者密碼進行登入,返回的是張三的使用者資訊。還帶回了其他欄位資訊回來了。