浏览代码

网易企业邮箱单点登录优化

MaxKey 2 年之前
父节点
当前提交
3222ba7043

+ 33 - 0
maxkey-protocols/maxkey-protocol-extendapi/src/main/java/org/maxkey/authz/exapi/endpoint/ExtendApiMetadata.java

@@ -0,0 +1,33 @@
+package org.maxkey.authz.exapi.endpoint;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.maxkey.authz.exapi.endpoint.adapter.netease.NeteaseRSATool;
+import org.maxkey.pretty.impl.JsonPretty;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+
+@Tag(name = "2-8-ExtendApi接口文档模块-元数据")
+@Controller
+public class ExtendApiMetadata {
+	final static Logger _logger = LoggerFactory.getLogger(ExtendApiMetadata.class);
+	
+	@Operation(summary = "netease qiye mail RSA Key", description = "网易企业邮箱RSA Key生成器",method="GET")
+	@RequestMapping(
+			value = "/metadata/netease/qiye/mail/rsa/gen",
+			method = {RequestMethod.POST, RequestMethod.GET})
+	@ResponseBody
+	public String  metadata(HttpServletRequest request,HttpServletResponse response) {
+		NeteaseRSATool neteaseRSATool =new NeteaseRSATool();
+		neteaseRSATool.genRSAKeyPair();
+		return JsonPretty.getInstance().formatln(neteaseRSATool);
+	}
+}

+ 37 - 31
maxkey-protocols/maxkey-protocol-extendapi/src/main/java/org/maxkey/authz/exapi/endpoint/adapter/ExtendApiQiye163ExmailAdapter.java → maxkey-protocols/maxkey-protocol-extendapi/src/main/java/org/maxkey/authz/exapi/endpoint/adapter/ExtendApiNeteaseQiyeMailAdapter.java

@@ -17,31 +17,32 @@
 
 package org.maxkey.authz.exapi.endpoint.adapter;
 
-import java.io.UnsupportedEncodingException;
-import java.security.interfaces.RSAPrivateKey;
-
+import org.apache.commons.lang3.StringUtils;
 import org.maxkey.authz.endpoint.adapter.AbstractAuthorizeAdapter;
-import org.maxkey.crypto.HexUtils;
-import org.maxkey.crypto.RSAUtils;
+import org.maxkey.authz.exapi.endpoint.adapter.netease.NeteaseRSATool;
 import org.maxkey.entity.Accounts;
+import org.maxkey.entity.ExtraAttr;
 import org.maxkey.entity.ExtraAttrs;
 import org.maxkey.entity.apps.Apps;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.web.servlet.ModelAndView;
+
+
 /**
  * qiye.163.com
  * @author shimingxy
  *
  */
-public class ExtendApiQiye163ExmailAdapter extends AbstractAuthorizeAdapter {
-	final static Logger _logger = LoggerFactory.getLogger(ExtendApiQiye163ExmailAdapter.class);
+public class ExtendApiNeteaseQiyeMailAdapter extends AbstractAuthorizeAdapter {
+	final static Logger _logger = LoggerFactory.getLogger(ExtendApiNeteaseQiyeMailAdapter.class);
 	//https://entryhz.qiye.163.com
-	static String REDIRECT_URI	
-			= "https://entryhz.qiye.163.com/domain/oa/Entry?domain=%s&account_name=%s&time=%s&enc=%s";
+	static String REDIRECT_PARAMETER	= "domain=%s&account_name=%s&time=%s&enc=%s&lang=%s";
+	
+	static String DEFAULT_REDIRECT_URI ="https://entryhz.qiye.163.com/domain/oa/Entry";
 
 	Accounts account;
-	
+
 	@Override
 	public Object generateInfo() {
 		return null;
@@ -51,38 +52,43 @@ public class ExtendApiQiye163ExmailAdapter extends AbstractAuthorizeAdapter {
 	public ModelAndView authorize(ModelAndView modelAndView) {
     	
 		Apps details=(Apps)app;
-		//extraAttrs from Applications
+		StringBuffer redirect_uri = new StringBuffer(details.getLoginUrl());
+		if(StringUtils.isNotBlank(redirect_uri)) {
+			if(redirect_uri.indexOf("?")>-1) {
+				redirect_uri.append("").append( REDIRECT_PARAMETER);
+			}else {
+				redirect_uri.append("?").append( REDIRECT_PARAMETER);
+			}
+		}
+		//extraAttrs from App
 		ExtraAttrs extraAttrs=null;
-		if(details.getIsExtendAttr()==1){
-			extraAttrs=new ExtraAttrs(details.getExtendAttr());
+		if(details.getIsExtendAttr() == 1){
+			extraAttrs = new ExtraAttrs(details.getExtendAttr());
+			for(ExtraAttr attr : extraAttrs.getExtraAttrs()) {
+				redirect_uri.append("&").append(attr.getAttr()).append("=").append(attr.getValue());
+			}
 		}
+		
 		String time = System.currentTimeMillis() + "";
 		//域名,请使用企业自己的域名
 		String domain = details.getPrincipal();
 		
-		String account_name = this.userInfo.getEmail();
+		String account_name = this.userInfo.getEmail().substring(0, this.userInfo.getEmail().indexOf("@"));
 		
-		//String lang = "0";
+		String lang = "0";
 		String src = account_name + domain + time;
 		
 		String privateKey = details.getCredentials();
-		String enc = null;
-		try {
-			enc = HexUtils.bytes2HexString(
-						RSAUtils.sign(
-								src.getBytes("UTF-8"), 
-								(RSAPrivateKey)RSAUtils.privateKey(HexUtils.hex2Bytes(privateKey)), 
-								null)
-					);
-			String loginUrl = String.format(REDIRECT_URI, domain,account_name,time,enc);
-			_logger.debug("LoginUrl {} " , loginUrl);
-			modelAndView.addObject("redirect_uri", loginUrl);
-		} catch (UnsupportedEncodingException e) {
-			_logger.error("UnsupportedEncodingException ", e);
-		} catch (Exception e) {
-			_logger.error("Exception ", e);
-		}
+		_logger.debug("Private Key {} " , privateKey);
+		
+		String enc = new NeteaseRSATool().generateSHA1withRSASigature(src, privateKey);
+		String loginUrl = String.format(redirect_uri.toString(), domain,account_name,time,enc,lang);
+		
+		_logger.debug("LoginUrl {} " , loginUrl);
+		modelAndView.addObject("redirect_uri", loginUrl);
         
         return modelAndView;
 	}
+    
+   
 }

+ 310 - 0
maxkey-protocols/maxkey-protocol-extendapi/src/main/java/org/maxkey/authz/exapi/endpoint/adapter/netease/NeteaseRSATool.java

@@ -0,0 +1,310 @@
+package org.maxkey.authz.exapi.endpoint.adapter.netease;
+
+import java.security.Key;
+import java.security.KeyFactory;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.Signature;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+import java.util.Base64;
+
+import javax.crypto.Cipher;
+
+import org.apache.commons.lang.ArrayUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NeteaseRSATool {
+
+	final static Logger _logger = LoggerFactory.getLogger(NeteaseRSATool.class);
+			
+	private static final char[] bcdLookup = { '0', '1', '2', '3', '4', '5',
+			'6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
+
+	private String description = "1024-bit RSA key";
+	private String priKey = null;
+	private String pubKey = null;
+	
+
+	public String bytesToHexStr(byte[] bcd) {
+		StringBuffer s = new StringBuffer(bcd.length * 2);
+
+		for (int i = 0; i < bcd.length; i++) {
+			s.append(bcdLookup[(bcd[i] >>> 4) & 0x0f]);
+			s.append(bcdLookup[bcd[i] & 0x0f]);
+		}
+
+		return s.toString();
+	}
+
+	public byte[] hexStrToBytes(String s) {
+		byte[] bytes;
+
+		bytes = new byte[s.length() / 2];
+
+		for (int i = 0; i < bytes.length; i++) {
+			bytes[i] = (byte) Integer.parseInt(s.substring(2 * i, 2 * i + 2),
+					16);
+		}
+
+		return bytes;
+	}
+
+	public void genRSAKeyPair() {
+		KeyPairGenerator rsaKeyGen = null;
+		KeyPair rsaKeyPair = null;
+		try {
+			_logger.trace("Generating a pair of RSA key ... ");
+			rsaKeyGen = KeyPairGenerator.getInstance("RSA");
+			SecureRandom random = new SecureRandom();
+			random.setSeed(System.currentTimeMillis());
+
+			rsaKeyGen.initialize(1024, random);
+
+			rsaKeyPair = rsaKeyGen.genKeyPair();
+			PublicKey rsaPublic = rsaKeyPair.getPublic();
+			PrivateKey rsaPrivate = rsaKeyPair.getPrivate();
+
+			pubKey = bytesToHexStr(rsaPublic.getEncoded());
+			priKey = bytesToHexStr(rsaPrivate.getEncoded());
+			_logger.trace("pubKey: {}" , pubKey);
+			_logger.trace("priKey: {}" , priKey);
+			_logger.trace("1024-bit RSA key GENERATED.");
+		} catch (Exception e) {
+			_logger.error("Exception genRSAKeyPair:" + e);
+		}
+	}
+
+	public String generateSHA1withRSASigature(String src, String priKey) {
+		try {
+			byte[] pribyte = hexStrToBytes(priKey.trim());
+			PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(pribyte);
+			KeyFactory fac = KeyFactory.getInstance("RSA");
+			RSAPrivateKey privateKey = (RSAPrivateKey) fac.generatePrivate(keySpec);
+			
+			Signature sigEng = Signature.getInstance("SHA1withRSA");
+			sigEng.initSign(privateKey);
+			sigEng.update(src.getBytes());
+			byte[] signature = sigEng.sign();
+			return bytesToHexStr(signature);
+		} catch (Exception e) {
+			e.printStackTrace();
+			return null;
+		}
+	}
+	
+	public String encryptWithPriKey(String src, String priKey) {
+		try {
+			byte[] pribyte = hexStrToBytes(priKey.trim());
+			PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(pribyte);
+			KeyFactory fac = KeyFactory.getInstance("RSA");
+			Key privateKey = fac.generatePrivate(keySpec);
+			
+			Cipher cipher = Cipher.getInstance("RSA");
+			cipher.init(Cipher.ENCRYPT_MODE, privateKey);
+			
+			byte[] bytes = src.getBytes();
+			byte[] encodedByteArray = new byte[] {};
+			for (int i = 0; i < bytes.length; i += 102){
+				byte[] subarray = ArrayUtils.subarray(bytes, i, i + 102);
+				byte[] doFinal = cipher.doFinal(subarray);
+				encodedByteArray = ArrayUtils.addAll(encodedByteArray, doFinal);
+			}
+			return bytesToHexStr(encodedByteArray);
+		} catch (Exception e) {
+			e.printStackTrace();
+			return null;
+		}
+	}
+
+	public boolean verifySHA1withRSASigature(String sign, String src,
+			String pubKeyStr) {
+		try {
+
+			Signature sigEng = Signature.getInstance("SHA1withRSA");
+
+			byte[] pubbyte = hexStrToBytes(pubKeyStr.trim());
+
+			X509EncodedKeySpec keySpec = new X509EncodedKeySpec(pubbyte);
+			KeyFactory fac = KeyFactory.getInstance("RSA");
+			RSAPublicKey pubKey = (RSAPublicKey) fac.generatePublic(keySpec);
+
+			sigEng.initVerify(pubKey);
+			sigEng.update(src.getBytes());
+
+			byte[] sign1 = hexStrToBytes(sign);
+			return sigEng.verify(sign1);
+
+		} catch (Exception e) {
+			e.printStackTrace();
+			return false;
+		}
+	}
+
+	
+	public String encryptLongTextWithPriKey(String src, String priKey) {
+		final int ENCRYPT_LENGTH = 117;
+		if (src.length() <= ENCRYPT_LENGTH) {
+			return encryptWithPriKey(src, priKey);
+		}
+		
+		StringBuffer sb = new StringBuffer();
+		int idx = 0;
+		while (idx < src.length()) {
+			int end = idx + ENCRYPT_LENGTH > src.length() ? src.length() : idx + ENCRYPT_LENGTH;
+			String sub = src.substring(idx, end);
+			String encSub = encryptWithPriKey(sub, priKey);
+			sb.append(encSub);
+			idx += ENCRYPT_LENGTH;
+		}
+		
+		return sb.toString();
+	}
+
+	public String encryptWithPriKeyWithBase64(String src, String priKey) {
+		try {
+			byte[] pribyte = hexStrToBytes(priKey.trim());
+			PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(pribyte);
+			KeyFactory fac = KeyFactory.getInstance("RSA");
+			Key privateKey = fac.generatePrivate(keySpec);
+			Cipher cipher = Cipher.getInstance("RSA");
+			cipher.init(Cipher.ENCRYPT_MODE, privateKey);
+			byte[] signature = cipher.doFinal(src.getBytes());
+
+			return Base64.getEncoder().encodeToString(signature).replaceAll("[^a-zA-Z0-9+/=]", "");
+		} catch (Exception e) {
+			e.printStackTrace();
+			return null;
+		}
+	}
+
+	public String encryptWithPubKey(String src, String pubKey) {
+		try {
+			byte[] pubbyte = hexStrToBytes(pubKey.trim());
+
+			X509EncodedKeySpec keySpec = new X509EncodedKeySpec(pubbyte);
+
+			KeyFactory fac = KeyFactory.getInstance("RSA");
+			Key publicKey = fac.generatePublic(keySpec);
+
+			Cipher cipher = Cipher.getInstance("RSA");
+			cipher.init(Cipher.ENCRYPT_MODE, publicKey);
+			byte[] signature = cipher.doFinal(src.getBytes());
+
+			return bytesToHexStr(signature);
+		} catch (Exception e) {
+			e.printStackTrace();
+			return null;
+		}
+	}
+
+	public String decryptWithPriKey(String enc, String priKey) {
+		try {
+			byte[] pribyte = hexStrToBytes(priKey.trim());
+
+			PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(pribyte);
+			KeyFactory fac = KeyFactory.getInstance("RSA");
+			RSAPrivateKey privateKey = (RSAPrivateKey) fac
+					.generatePrivate(keySpec);
+
+			// privateKey.getModulus() + privateKey.getPrivateExponent() +
+			// privateKey.getAlgorithm();
+
+			Cipher cipher = Cipher.getInstance("RSA");
+			cipher.init(Cipher.DECRYPT_MODE, privateKey);
+
+			byte[] forumcookie = hexStrToBytes(enc);
+
+			byte[] plainText = cipher.doFinal(forumcookie);
+
+			return bytesToHexStr(plainText);
+
+		} catch (Exception e) {
+			e.printStackTrace();
+			return null;
+		}
+	}
+
+	public String decryptWithPubKey(String enc, String pubKey) {
+		try {
+			byte[] pubbyte = hexStrToBytes(pubKey.trim());
+
+			X509EncodedKeySpec keySpec = new X509EncodedKeySpec(pubbyte);
+			KeyFactory fac = KeyFactory.getInstance("RSA");
+			Key publicKey = fac.generatePublic(keySpec);
+
+			Cipher cipher = Cipher.getInstance("RSA");
+			cipher.init(Cipher.DECRYPT_MODE, publicKey);
+
+			byte[] forumcookie = hexStrToBytes(enc);
+
+			byte[] plainText = cipher.doFinal(forumcookie);
+
+			return new String(plainText);
+
+		} catch (Exception e) {
+			System.err.println(e);
+			e.printStackTrace(System.err);
+			return null;
+		}
+	}
+
+	public RSAPrivateKey getPriKey(String priKey) {
+		try {
+			byte[] pribyte = hexStrToBytes(priKey.trim());
+
+			PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(pribyte);
+			KeyFactory fac = KeyFactory.getInstance("RSA");
+			RSAPrivateKey key = (RSAPrivateKey) fac.generatePrivate(keySpec);
+			return key;
+
+		} catch (Exception e) {
+			e.printStackTrace();
+			return null;
+		}
+	}
+
+	public RSAPublicKey getPubKey(String pubKey) {
+		try {
+			byte[] pubbyte = hexStrToBytes(pubKey.trim());
+
+			X509EncodedKeySpec keySpec = new X509EncodedKeySpec(pubbyte);
+			KeyFactory fac = KeyFactory.getInstance("RSA");
+			RSAPublicKey key = (RSAPublicKey) fac.generatePublic(keySpec);
+			return key;
+		} catch (Exception e) {
+			e.printStackTrace();
+			return null;
+		}
+	}
+
+	public String getPri() {
+		return priKey;
+	}
+
+	public void setPri(String pri) {
+		this.priKey = pri;
+	}
+
+	public String getPub() {
+		return pubKey;
+	}
+
+	public void setPub(String pub) {
+		this.pubKey = pub;
+	}
+
+	public String getDescription() {
+		return description;
+	}
+
+	public void setDescription(String description) {
+		this.description = description;
+	}
+}