单点登录

您所在的位置:网站首页 领星erp登录入口网址 单点登录

单点登录

2024-06-23 05:41| 来源: 网络整理| 查看: 265

一.功能价值简述

用户第三方系统与领星实现登录集成,实现双系统无缝登录打通

 

二.操作说明 1、配置单点登录功能

      在【业务配置】-【全局】-【单点登录设置】中打开单点登录配置对单点登录方式进行配置。

单点登录方式:目前仅支持JWT

验签算法:目前仅支持HS256

验签密钥:双方约定对称加密秘钥,不能低于32个字符,不能超过256个字符

企业唯一标识:进行单点登录时候校验企业唯一标识符,通过此编号可以识别你的企业ID

未映射用户处理方式:

类型

处理规则

创建(默认)

当根据用户唯一性映射字段,进行映射时候,如果检测不到此用户,则自动创建一个新用户。

适用于全部用户在鉴权系统管理,领星不管理用户客户使用

禁止登录

当映射不到用户时候,禁止此用户登录系统。

适用于领星有独立的一套用户管理体系,只有创建并配置好映射的用户能够实现单点登录。

用户唯一性映射字段:

首次单点登录时候,进行验证的唯一字段,首次映射之后,会绑定双向的唯一ID,后续变更手机号或者真实姓名都不影响单点登录功能使用。

手机号映射:选定手机号映射时,手机号不允许为空。 邮箱映射:选定邮箱映射时,邮箱不允许为空。 用户名映射:选定用户名映射时,用户名不允许为空。 2、JWT基本格式

JWT是由三段信息构成的,将这三段信息文本用"."链接一起就构成了JWT字符串。以下为示例

eyJ0eXAiOiJKV1QiLCJ0eXBlIjoiSldUIiwiYWxnIjoiSFMyNTYifQ.eyJzdWIiOiJ1c2VySWQwMDEiLCJtb2JpbGUiOiIxMDAwIiwiZXhwIjoxNjgzNTE3OTg5LCJlbWFpbCI6Imxpbmd4aW5nVXNlckBpbmd4aW5nLmNvbSIsInVzZXJuYW1lIjoibGluZ3hpbmdVc2VyIiwicmVhbG5hbWUiOiLpoobmmJ_nlKjmiLcifQ.hnTxa5qkg6HD8xinBjF2VPnfH6WKuhzh8qORYq8ljMI

    

第一部分是header,明文是{"typ":"JWT","alg":"HS256"},经过base64URL编码之后是eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9 第二部分是payload,明文是{"sub":"userId001,"exp":"1683517989095","mobile":"10000","email":"[email protected]", "username":""lingxingUser,"realname":"领星用户"} (其中sub是必须字段,mobile/email/username则根据jwt配置信息中的唯一映射字段填写),经过base64URL编码之后是eyJzdWIiOiJ1c2VySWQwMDEiLCJtb2JpbGUiOiIxMDAwIiwiZXhwIjoxNjgzNTE3OTg5LCJlbWFpbCI6Imxpbmd4aW5nVXNlckBpbmd4aW5nLmNvbSIsInVzZXJuYW1lIjoibGluZ3hpbmdVc2VyIiwicmVhbG5hbWUiOiLpoobmmJ_nlKjmiLcifQ 第三部分是signature,由第一部分的header+"."+第二部分的payload得到需要签名的信息是eyJ0eXAiOiJKV1QiLCJ0eXBlIjoiSldUIiwiYWxnIjoiSFMyNTYifQ.eyJzdWIiOiJ1c2VySWQwMDEiLCJtb2JpbGUiOiIxMDAwIiwiZXhwIjoxNjgzNTE3OTg5LCJlbWFpbCI6Imxpbmd4aW5nVXNlckBpbmd4aW5nLmNvbSIsInVzZXJuYW1lIjoibGluZ3hpbmdVc2VyIiwicmVhbG5hbWUiOiLpoobmmJ_nlKjmiLcifQ,经过相应签名算法签名以后(在本例中就是HS256),再通过base64URL编码得到签名是hnTxa5qkg6HD8xinBjF2VPnfH6WKuhzh8qORYq8ljMI以上为jwt生成过程的基本说明,具体细节以及实现库可以通过JWT官网进一步了解。

 

3、JAVA开发实例 3.1 基于自定义实现 1、pom引入JWT依赖包 com.auth0 java-jwt 3.16.0 2、Java示例代码 package com.asinking.cloud.uc.admin.util; import com.alibaba.fastjson.JSON; import com.auth0.jwt.JWT; import com.auth0.jwt.algorithms.Algorithm; import javax.crypto.Cipher; import java.net.URLEncoder; import java.security.KeyFactory; import java.security.PrivateKey; import java.security.spec.PKCS8EncodedKeySpec; import java.util.Base64; import java.util.Date; import java.util.HashMap; import java.util.Map; /** *

* SSO-JWT第三方系统代码示例 *

*/ public class SSOJwtUtil { private static final String PRIVATE_KEY = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAMl5dXIwbawEOpMY+x02TRMhRXl0Ng4fbF0xofgCRfPkeO9JKU/An4+MtSyXDQNEGh+Eb8e1M2zJ4M7zf3DZ2wBcXn3247xKK8xol8VW2ytuGm5yBvtQpuuwwMTuf4k5rmQj4cMW4Ob2hIumjI4TiwwpEV0CIN4HKsLPXmC2EMsdAgMBAAECgYA/51F0NZ4jqHe3vn2vx1BtF+mEW3LlydvCN4LrOjVb5YTiSO9ch3lUu8mfag3LkmdCxev6iSPVhrbSjXNHpSIMC/xKk/FMjKGXCCsMt8DTzIgOSS8V+7TSr/vxwOOEmQyYxrjdS748dXlAlQ8YslbUxIWO34qFLjpG+YkIb9JvNQJBAO9Ec9P9IQAuslcrhH4Lpph8PHaTdKp+R4xHbx2hbmTdgTg+cYKBTVGec3Caeocr8VgtfSZgPBJGEJi7RNcfXk8CQQDXkGh+dHYli7Sz/Cj4RQzXWAlmaw0Jgmc4eoucj5BGtM85ZtmSKZUXTM3iLidiD8euyOlEIgOL/15o1abNdPDTAkEA7oa5Sd6RZZMn60rQ3K9Ut7Myu6sopUcaoLgeB9YFLby8s4tcsZOhtvpVby4xdEvUX+mJWBacDEOZDAm1CRiWdQJAWpj+0ebwoOcOk3avYWjj9L2zdbAYUp7T8xDODIbqBE2Jqn5ngt6nIpvNC/qJ4tTu/67BGzmQdA5oB3eEG2XCsQJAQinkQqRb42t+yn7AbKm5vx9kFs0r3wlBYihYguM5HU/W2HYS5iyY1r2EmYpaJiHrKGXnND61w3N0k8GSMVD7uA=="; private static final String URL_PARAM = "?authType=jwt¶m=%s"; /** * TODO 需要替换为客户访问领星ERP系统的域名,SAAS客户统一为 https://erp.lingxing.com,独立部署客户需要替换为自己的服务域名 * 如果需要登录默认进入指定菜单,请携带具体路径 * eg: 默认进入用户管理页面, https://erp.lingxing.com/erp/muser/userManage */ private static final String DOMAIN = "https://erp.lingxing.com"; // TODO 需要替换为配置在ERP系统的验签密钥字段值 (菜单路径:设置/业务配置/全局/单点登录设置:验签密钥) private static final String SIGN_KEY = "387e98090e064129886e959a94f7aea2"; // TODO 需替换为配置在ERP系统的企业唯一标识值 (菜单路径:设置/业务配置/全局/单点登录设置:企业唯一标识) private static final String CLIENT_ID = "4B008083446B05FAE42589CEEEBD611A "; // TODO 如果需要指定当前jwtToken的过期时间,请手动调整此项值 public static final Long EXPIRE_TIME = 3600L;//过期时间,单位秒,默认一小时 public static void main(String[] args) { // TODO 用户信息需替换为本系统的用户数据 String uniqueKey = "userId001"; String mobile = "10000"; String email = "[email protected]"; String username = "lingxingUser"; String realname = "领星用户"; String redirectUrl = getRedirectUrl(uniqueKey, mobile, email, username, realname); System.out.println("redirectUrl:" + redirectUrl); } /** * 获取重定向到领星ERP系统的地址 * @param uniqueKey * @param mobile * @param email * @param username * @param realname * @return */ public static String getRedirectUrl(String uniqueKey, String mobile, String email, String username, String realname ){ String jwtToken = createJWTToken(uniqueKey, mobile, email, username, realname); String jwtSSOLoginParam = encodeJwtSSOLoginParam(CLIENT_ID, jwtToken); return DOMAIN + String.format(URL_PARAM, jwtSSOLoginParam); } /** * 加密单点登录入参内容 * @param clientId 企业唯一标识 * @param jwtToken token信息 * @return */ private static String encodeJwtSSOLoginParam(String clientId, String jwtToken) { Map param = new HashMap(); param.put("jwtToken", jwtToken); param.put("clientId", clientId); return encrypt(JSON.toJSONString(param), PRIVATE_KEY); } /** * 生成JWT-TOKEN * @return */ private static String createJWTToken(String uniqueKey, String mobile, String email, String username, String realname) { Map header = new HashMap(); header.put("type", "JWT"); header.put("alg","HS256"); Date exp = new Date(new Date().getTime() + EXPIRE_TIME * 1000); return JWT.create() .withHeader(header) .withSubject(uniqueKey) .withExpiresAt(exp) .withClaim("mobile", mobile) .withClaim("email", email) .withClaim("username", username) .withClaim("realname", realname) .withClaim("timestamp", System.currentTimeMillis()) .sign(Algorithm.HMAC256(SIGN_KEY)); } /** * RSA加密 - 私钥分段加密 * @param content * @param privateKeyStr * @return */ private static String encrypt(String content, String privateKeyStr) { try { // 获取私钥 PrivateKey privateKey = getPrivateKey(privateKeyStr); Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.ENCRYPT_MODE, privateKey); // URLEncoder编码解决中文乱码问题 byte[] data = URLEncoder.encode(content, "UTF-8").getBytes("UTF-8"); // 加密时超过117字节就报错。为此采用分段加密的办法来加密 byte[] enBytes = null; for (int i = 0; i < data.length; i += 117) { // 注意要使用2的倍数,否则会出现加密后的内容再解密时为乱码 byte[] doFinal = cipher.doFinal(subarray(data, i, i + 117)); enBytes = addAll(enBytes, doFinal); } return Base64.getEncoder().encodeToString(enBytes).replaceAll("\\+", "-").replaceAll("/", "_").replaceAll("=", ""); } catch(Exception e) { throw new RuntimeException("UC-RSA加密出错"); } } /** * 将base64编码后的私钥字符串转成PrivateKey实例 * @param privateKey 私钥 * @return PrivateKey实例 * @throws Exception 异常信息 */ private static PrivateKey getPrivateKey(String privateKey) throws Exception { byte[] keyBytes = Base64.getDecoder().decode(privateKey); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); return keyFactory.generatePrivate(keySpec); } private static byte[] subarray(byte[] array, int startIndexInclusive, int endIndexExclusive) { if (array == null) { return null; } else { if (startIndexInclusive < 0) { startIndexInclusive = 0; } if (endIndexExclusive > array.length) { endIndexExclusive = array.length; } int newSize = endIndexExclusive - startIndexInclusive; if (newSize


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3