From 12ba7f9114c3da3e6d4f041a87402d987e98b1d7 Mon Sep 17 00:00:00 2001 From: codingXiaxw Date: Fri, 16 Aug 2024 17:43:44 +0800 Subject: [PATCH] =?UTF-8?q?JSY-42593=20update=EF=BC=9A=E4=BE=9D=E8=B5=96?= =?UTF-8?q?=E9=97=AE=E9=A2=98=20&&=20=E4=BF=AE=E6=94=B9=E5=8C=85=E8=B7=AF?= =?UTF-8?q?=E5=BE=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{ => hihidata}/sso/bean/SSOSamlBean.java | 2 +- .../sso/bean/SSOSamlResultBean.java | 2 +- .../sso/controller/SSOController.java | 17 +- .../{ => hihidata}/sso/filter/SAMLFilter.java | 7 +- .../sso/service/SSOService.java | 5 +- .../sso/service/impl/SSOServiceImpl.java | 240 ++++++++++++++++++ .../sso/utils/OpenSAMLUtils.java | 6 +- .../sso/utils/XMLAnalysisUtils.java | 16 +- .../sso/service/impl/SSOServiceImpl.java | 172 ------------- 9 files changed, 265 insertions(+), 202 deletions(-) rename src/main/java/com/fanruan/{ => hihidata}/sso/bean/SSOSamlBean.java (98%) rename src/main/java/com/fanruan/{ => hihidata}/sso/bean/SSOSamlResultBean.java (97%) rename src/main/java/com/fanruan/{ => hihidata}/sso/controller/SSOController.java (76%) rename src/main/java/com/fanruan/{ => hihidata}/sso/filter/SAMLFilter.java (77%) rename src/main/java/com/fanruan/{ => hihidata}/sso/service/SSOService.java (88%) create mode 100644 src/main/java/com/fanruan/hihidata/sso/service/impl/SSOServiceImpl.java rename src/main/java/com/fanruan/{ => hihidata}/sso/utils/OpenSAMLUtils.java (88%) rename src/main/java/com/fanruan/{ => hihidata}/sso/utils/XMLAnalysisUtils.java (91%) delete mode 100644 src/main/java/com/fanruan/sso/service/impl/SSOServiceImpl.java diff --git a/src/main/java/com/fanruan/sso/bean/SSOSamlBean.java b/src/main/java/com/fanruan/hihidata/sso/bean/SSOSamlBean.java similarity index 98% rename from src/main/java/com/fanruan/sso/bean/SSOSamlBean.java rename to src/main/java/com/fanruan/hihidata/sso/bean/SSOSamlBean.java index 7164965..b3409f9 100644 --- a/src/main/java/com/fanruan/sso/bean/SSOSamlBean.java +++ b/src/main/java/com/fanruan/hihidata/sso/bean/SSOSamlBean.java @@ -1,4 +1,4 @@ -package com.fanruan.sso.bean; +package com.fanruan.hihidata.sso.bean; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; diff --git a/src/main/java/com/fanruan/sso/bean/SSOSamlResultBean.java b/src/main/java/com/fanruan/hihidata/sso/bean/SSOSamlResultBean.java similarity index 97% rename from src/main/java/com/fanruan/sso/bean/SSOSamlResultBean.java rename to src/main/java/com/fanruan/hihidata/sso/bean/SSOSamlResultBean.java index 74ac4c4..a02ac66 100644 --- a/src/main/java/com/fanruan/sso/bean/SSOSamlResultBean.java +++ b/src/main/java/com/fanruan/hihidata/sso/bean/SSOSamlResultBean.java @@ -1,4 +1,4 @@ -package com.fanruan.sso.bean; +package com.fanruan.hihidata.sso.bean; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; diff --git a/src/main/java/com/fanruan/sso/controller/SSOController.java b/src/main/java/com/fanruan/hihidata/sso/controller/SSOController.java similarity index 76% rename from src/main/java/com/fanruan/sso/controller/SSOController.java rename to src/main/java/com/fanruan/hihidata/sso/controller/SSOController.java index fe003f0..583339a 100644 --- a/src/main/java/com/fanruan/sso/controller/SSOController.java +++ b/src/main/java/com/fanruan/hihidata/sso/controller/SSOController.java @@ -1,16 +1,7 @@ -package com.fanruan.sso.controller; - -import com.fanruan.hihidata.action.aspect.PortalRoleCheck; -import com.fanruan.hihidata.action.aspect.RateLimit; -import com.fanruan.hihidata.action.aspect.Scope; -import com.fanruan.hihidata.action.reponse.HiRespond; -import com.fanruan.hihidata.config.role.CorpVersionRoleType; -import com.fanruan.hihidata.service.sso.SSOService; -import com.fanruan.hihidata.service.utils.OpenSAMLUtils; -import com.fr.decision.webservice.annotation.LoginStatusChecker; -import com.fr.third.org.apache.commons.lang3.StringUtils; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; +package com.fanruan.hihidata.sso.controller; + +import com.fanruan.hihidata.sso.service.SSOService; +import com.fanruan.hihidata.sso.utils.OpenSAMLUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; diff --git a/src/main/java/com/fanruan/sso/filter/SAMLFilter.java b/src/main/java/com/fanruan/hihidata/sso/filter/SAMLFilter.java similarity index 77% rename from src/main/java/com/fanruan/sso/filter/SAMLFilter.java rename to src/main/java/com/fanruan/hihidata/sso/filter/SAMLFilter.java index cd7a2fe..8a31834 100644 --- a/src/main/java/com/fanruan/sso/filter/SAMLFilter.java +++ b/src/main/java/com/fanruan/hihidata/sso/filter/SAMLFilter.java @@ -1,4 +1,4 @@ -package com.fanruan.sso.filter; +package com.fanruan.hihidata.sso.filter; @@ -9,11 +9,10 @@ import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class SAMLFilter { - private final SamlIgnores ignores = new SamlIgnores(); + private boolean initialized = false; - @Override public void doFilter(HttpServletRequest req, HttpServletResponse res, FilterChain filterChain) throws IOException, ServletException { - // do something + // do something filter filterChain.doFilter(req, res); } diff --git a/src/main/java/com/fanruan/sso/service/SSOService.java b/src/main/java/com/fanruan/hihidata/sso/service/SSOService.java similarity index 88% rename from src/main/java/com/fanruan/sso/service/SSOService.java rename to src/main/java/com/fanruan/hihidata/sso/service/SSOService.java index 576294f..cde9f14 100644 --- a/src/main/java/com/fanruan/sso/service/SSOService.java +++ b/src/main/java/com/fanruan/hihidata/sso/service/SSOService.java @@ -1,6 +1,7 @@ -package com.fanruan.sso.service; +package com.fanruan.hihidata.sso.service; -import com.fanruan.hihidata.bean.sso.SSOSamlBean; + +import com.fanruan.hihidata.sso.bean.SSOSamlBean; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; diff --git a/src/main/java/com/fanruan/hihidata/sso/service/impl/SSOServiceImpl.java b/src/main/java/com/fanruan/hihidata/sso/service/impl/SSOServiceImpl.java new file mode 100644 index 0000000..74ceebc --- /dev/null +++ b/src/main/java/com/fanruan/hihidata/sso/service/impl/SSOServiceImpl.java @@ -0,0 +1,240 @@ +package com.fanruan.hihidata.sso.service.impl; + +import com.fanruan.hihidata.sso.bean.SSOSamlBean; +import com.fanruan.hihidata.sso.utils.XMLAnalysisUtils; +import com.fanruan.hihidata.sso.service.SSOService; +import com.fasterxml.jackson.databind.JsonNode; +import com.onelogin.saml2.Auth; +import com.onelogin.saml2.authn.AuthnRequestParams; +import com.onelogin.saml2.logout.LogoutRequestParams; +import com.onelogin.saml2.settings.Saml2Settings; +import com.onelogin.saml2.settings.SettingsBuilder; +import com.onelogin.saml2.util.Util; +import org.apache.commons.lang3.RandomUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; +import org.springframework.web.util.WebUtils; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.security.PrivateKey; +import java.security.cert.X509Certificate; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.UUID; + + +@Service +public class SSOServiceImpl implements SSOService { + + private static final String UPPERCASE_RULER = "uppercase"; + private static final String LOWERCASE_RULER = "lowercase"; + private static final String RELAY_STATE = "RelayState"; + + @Override + public String generateSpMetadata(String registrationId) throws Exception { + Saml2Settings settings = getConfig(getSamlSpConfig(registrationId)); + settings.setSPValidationOnly(true); + String metadata = settings.getSPMetadata(); + List errors = Saml2Settings.validateMetadata(metadata); + if (errors.isEmpty()) { + return metadata; + } else { + StringBuilder errorsBuilder = new StringBuilder(); + for (String error : errors) { + errorsBuilder.append(error); + } + return errorsBuilder.toString(); + } + } + + @Override + public void slo(String registrationId, HttpServletRequest req, HttpServletResponse res) throws Exception { + Saml2Settings settings = getConfig(getSamlSpConfig(registrationId)); + Auth auth = new Auth(settings, req, res); + auth.processSLO(); +// LoginService.getInstance().crossDomainLogout(req, res, "callback").createCrossDomainResponse(); + auth.logout(); + } + + @Override + public String logout(String registrationId, HttpServletRequest req, HttpServletResponse res) throws Exception { + Saml2Settings settings = getConfig(getSamlSpConfig(registrationId)); + Auth auth = new Auth(settings, req, res); + return auth.logout(StringUtils.EMPTY, new LogoutRequestParams(), true); + } + + @Override + public String acs(String registrationId, HttpServletRequest request, HttpServletResponse response) throws Exception { + Saml2Settings settings = getConfig(getSamlSpConfig(registrationId)); + Auth auth = new Auth(settings, request, response); + auth.processResponse(); + String lastResponseXML = auth.getLastResponseXML(); +// FineLoggerFactory.getLogger().info("registrationId is {}, The xml is: {}", registrationId, lastResponseXML); + + // 先校验下responese的合法性 + // String username = XMLAnalysisUtils.getUserName(lastResponseXML); + String memberName = XMLAnalysisUtils.getMemberName(lastResponseXML); + String corpId = XMLAnalysisUtils.getCorpId(lastResponseXML); + // 解析出relayState +// String relayState = WebUtils.getHTTPRequestParameter(request, RELAY_STATE); + String relayState = StringUtils.EMPTY; +// if (Objects.isNull(user)) { +// // 走注册逻辑 +// String newUserId = UUID.randomUUID().toString(); +// return ssoLogin(request, response, corpId, relayState, registrationId); +// } + return ssoLogin(request, response, corpId, relayState, registrationId); + } + + private String ssoLogin(HttpServletRequest request, HttpServletResponse response, String corpId, + String relayState, String registrationId) throws Exception { + // 登录 +// corpService.reLogin(request, response, newUser, corpId); + String serviceUrl = "http://localhost:8081/decision/home"; + String loginUrl = "http://localhost:8081/decision/login"; + request.getSession().setAttribute("sso_login", registrationId); + if (StringUtils.isNotEmpty(relayState)) { + response.sendRedirect(serviceUrl); + return StringUtils.EMPTY; + } + response.sendRedirect(loginUrl); + return StringUtils.EMPTY; + } + + public Saml2Settings getConfig(SSOSamlBean ssoSamlBean) throws Exception { + Map samlData = new HashMap<>(); + + String spAcsUrl = "http://localhost:8081/sso/saml/xxx/acs"; + String spEntityId = "http://localhost:8081/sso/saml/xxx/iss"; + samlData.put("onelogin.saml2.sp.entityid", spEntityId); + samlData.put("onelogin.saml2.sp.assertion_consumer_service.url", spAcsUrl); + + //IDP配置 + String idpEntityId = ssoSamlBean.getIssuer(); + String idpSignInUrl = ssoSamlBean.getSsoEndpoint(); + String idpPublicKey = ssoSamlBean.getSignatureCrt(); + String idpLogOutUrl = ssoSamlBean.getSloEndpoint(); + + samlData.put("onelogin.saml2.idp.single_sign_on_service.url", idpSignInUrl); + samlData.put("onelogin.saml2.idp.entityid", idpEntityId); + X509Certificate idpX509CertInstance = Util.loadCert((idpPublicKey).trim()); + samlData.put("onelogin.saml2.idp.x509cert", idpX509CertInstance); + + String cert = ssoSamlBean.getSpCrt(); + X509Certificate spX509CertInstance = Util.loadCert(cert.trim()); + samlData.put("onelogin.saml2.sp.x509cert", spX509CertInstance); + + String privateKey = ssoSamlBean.getSpPrivateKey(); + PrivateKey spPrivateKey = Util.loadPrivateKey(privateKey.trim()); + samlData.put("onelogin.saml2.sp.privatekey", spPrivateKey); + + samlData.put("onelogin.saml2.security.authnrequest_signed", true); + samlData.put("onelogin.saml2.security.logoutrequest_signed", true); + //签名断言和加密断言的功能都默认开启了,增加安全性 + samlData.put("onelogin.saml2.security.want_assertions_signed", true); + samlData.put("onelogin.saml2.security.want_assertions_encrypted", true); + samlData.put("onelogin.saml2.security.want_nameid_encrypted", true); + samlData.put("onelogin.saml2.idp.single_logout_service.url", idpLogOutUrl); + + SettingsBuilder builder = new SettingsBuilder(); + Saml2Settings settings = builder.fromValues(samlData).build(); + + return settings; + } + + @Override + public SSOSamlBean getSamlSpConfig(String registrationId) throws Exception { + String spCrt = "-----BEGIN CERTIFICATE-----\n" + + "MIIDcDCCAlgCCQDVWvep1uXiejANBgkqhkiG9w0BAQsFADB6MUUwQwYDVQQIDDxv\n" + + "cGVuc3NsIHJlcSAtbmV3IC1rZXkgcnAtcHJpdmF0ZS5rZXkgLW91dCBycC1jZXJ0\n" + + "aWZpY2F0ZS5jc3IxDTALBgNVBAcMBHd1eGkxEDAOBgNVBAoMB2ZhbnJ1YW4xEDAO\n" + + "BgNVBAsMB2ZhbnJ1YW4wHhcNMjQwODA4MTEyNjIzWhcNMjUwODA4MTEyNjIzWjB6\n" + + "MUUwQwYDVQQIDDxvcGVuc3NsIHJlcSAtbmV3IC1rZXkgcnAtcHJpdmF0ZS5rZXkg\n" + + "LW91dCBycC1jZXJ0aWZpY2F0ZS5jc3IxDTALBgNVBAcMBHd1eGkxEDAOBgNVBAoM\n" + + "B2ZhbnJ1YW4xEDAOBgNVBAsMB2ZhbnJ1YW4wggEiMA0GCSqGSIb3DQEBAQUAA4IB\n" + + "DwAwggEKAoIBAQDS0iT7OyG3Y1+3mLfXeoAFZLgiwUel143W5gdlbXSHbuJ0xNrE\n" + + "vaGRaUj0vZCdVPL6bAtQiJGQGAEgYpp9ZeaPexCrOE92LhHGZADbcVT2B954ni+f\n" + + "LKG7J9FnZcRDOBEqYhyVqTvG6uN0TIIkRwKFTjsSPdRQyqV6uNW4y+r8RrjIOAMS\n" + + "K5CWKZbqiiAcb5EqmeYQfWNLjVCn+E199R1LIlEnrMz4+kHEIOTTzNQht30utx5f\n" + + "aiBlLQ9XVyVPWHV0iNzGs2qxHUA07bZyEuiG2t+79OAQWKzjqTK5GTvAWEbZ6IaO\n" + + "FVi970pG7E14T+rivZGqJrLWvv8MvW4BE0v7AgMBAAEwDQYJKoZIhvcNAQELBQAD\n" + + "ggEBAFAZg0TGNSpnIKR1MW4Y0K+2LyslBlMTirrQY21MobS/S+WM8QE+qZvyPUpp\n" + + "ilaXnquCptM1MtX/9kPRlRA5v8bEWNZQA6bs3RkH5FC5j+TKcrPti7yAaTcMxw7h\n" + + "S/e9e3HZ9ZeU2b1M87Gs1uGTWJ4LyH5vKfHRpNlhOj+rv4k8UeCce/ER0z4OBmwE\n" + + "0OtY7xWEP5arF6iVyntpYPbxujuxui1orfsUl5DEOUvKA3VHG5fsgUkhP/KoxFTS\n" + + "6ETrC5qy7HCk9J88HX9ovxY/bj/SWwAGx3wNaG+NZz2pQyD6NaBOSRvBC2ZwFlWr\n" + + "TgtYc4URcnVH2DOkamR9hFecVA4=\n" + + "-----END CERTIFICATE-----"; + String spKey = "-----BEGIN RSA PRIVATE KEY-----\n" + + "MIIEpAIBAAKCAQEA0tIk+zsht2Nft5i313qABWS4IsFHpdeN1uYHZW10h27idMTa\n" + + "xL2hkWlI9L2QnVTy+mwLUIiRkBgBIGKafWXmj3sQqzhPdi4RxmQA23FU9gfeeJ4v\n" + + "nyyhuyfRZ2XEQzgRKmIclak7xurjdEyCJEcChU47Ej3UUMqlerjVuMvq/Ea4yDgD\n" + + "EiuQlimW6oogHG+RKpnmEH1jS41Qp/hNffUdSyJRJ6zM+PpBxCDk08zUIbd9Lrce\n" + + "X2ogZS0PV1clT1h1dIjcxrNqsR1ANO22chLohtrfu/TgEFis46kyuRk7wFhG2eiG\n" + + "jhVYve9KRuxNeE/q4r2Rqiay1r7/DL1uARNL+wIDAQABAoIBAFq4h6V8+rNaFhSB\n" + + "qYsWcgTgJMT/+38IVUdG0aP6CA1H0DeDhsjm+aIDdpuq/5JUvgK5f9z2B/3D9qgj\n" + + "Bmwz75WK1c94eelXRdrjqeLE0FTXagrpt4B9ylMpfVlLV7u9YtWkRry4iLq+1YZ0\n" + + "bgSCcjk/QvhElxr1OWSoKYBOcB6C39o96Obzek6cgdUNRZpP1pnyNpYMAnrHUOnR\n" + + "a+iFMFt3q7Pn815EG4Rg4Emgmd9v9c/xAonrqoXddZSsCfUTo1duqfoxJnU21O3q\n" + + "spcofbX25sULYL1gpM4p1V92hHaSNZHdZhxMlUuSCwBk1PJEGLrFEDiVZXXDcH8m\n" + + "B8ghZrECgYEA/H/gz0rkNW6zk1nMKT/ozJUb0XqTVZBrJuq7L0vmOUuNUMalbkzA\n" + + "GlDUM7r852yeiwx4S+XgTRvWRsqau/cuX1B+Z4qaLjWi7RUrQqI9iZS3HFbdX21R\n" + + "pXz03iCPONL+X4Mzh6Z7NIKf8ptn4syMXJan1M5XrsM8bPAS1oRyuf8CgYEA1b5Z\n" + + "Pkzk6N6GqGVzfNQ8G3l4620rbJBvc1itNTK4TX1W9MOKIHj/zoYopgk+2snQQtUd\n" + + "2Urg+3LzJ7vegBmt8Mlpjs6Y27Iz4gyurWHAYEkBK/weqExOz6QB1lYFaO3DPHcx\n" + + "+SJc2tSmoBEvcLmEBfvJ0uIvN637BmyPg7umVgUCgYEAgwV8SzRqXMuXxTNIfHMc\n" + + "QuRwre9z+mdZIrWU8gLpcPuiVbLubuDGoiElK76wswmq7y5GUePz0y9Jriw9xKGL\n" + + "34uuO94xCR9t7qYYb5guZHDV34+3iWf5gOzpR0YP64WY10kGeTJLJkFN7B719jr7\n" + + "7qOCbSuxVg8bENA2hjfuLFMCgYEAp60PrYP8/4Gx+WC83GxSSutcJLQboKseA0rJ\n" + + "djY3xvJQyOqs7RR++LDeKoKOQGyZaBRvugq3vApNHhqPTcbXYVFf8Zu45oBBm09/\n" + + "qJxKoj4jITJDiptyKAntNwt8avg6dLC9D0gZt8GihWd14+Rk4ZzIkxrFF9TwW/XG\n" + + "D/2hW1ECgYBQtU5PYiaMb7zTVQVVS7aVbym6QInvyZ03O64Y3y+cLf+PFG3F6q/4\n" + + "SRtsmILe+sBY8MdQj0gvGBguMRTgprahS38mbQLdyGCmJIsKdqk9IHv4xU9sHU+n\n" + + "xoznawU1UDlxxWrfBpaYVb4CkxaDjL5FvWHv74ZgZ1+Zh3e0gCuIzQ==\n" + + "-----END RSA PRIVATE KEY-----\n"; + + String ssoEndpoint = "https://codingxiaxw.onelogin.com/trust/saml2/http-post/sso/36c59575-2adb-4fd8-9eb7-c5c93ffbc5fe3"; + String signatureAlg = "SHA-1"; + String signatureCrt = "-----BEGIN CERTIFICATE-----\n" + + "MIID3DCCAsSgAwIBAgIUB2/7G0jrXZEpZqCOClAOw9tM0gswDQYJKoZIhvcNAQEF\n" + + "BQAwRTEQMA4GA1UECgwHRmFucnVhbjEVMBMGA1UECwwMT25lTG9naW4gSWRQMRow\n" + + "GAYDVQQDDBFPbmVMb2dpbiBBY2NvdW50IDAeFw0yNDA4MDEwMzM3MzZaFw0yOTA4\n" + + "MDEwMzM3MzZaMEUxEDAOBgNVBAoMB0ZhbnJ1YW4xFTATBgNVBAsMDE9uZUxvZ2lu\n" + + "IElkUDEaMBgGA1UEAwwRT25lTG9naW4gQWNjb3VudCAwggEiMA0GCSqGSIb3DQEB\n" + + "AQUAA4IBDwAwggEKAoIBAQCWV9aev80yVah8cbhq3JYSn30GiJQFXPXX09zPzztO\n" + + "FcvnKsskx5oRj0DXVuhGwPEaQ4b2wMahMNHoGVVuMFAs1xPa55lxcY4XirEhY/nW\n" + + "i9CYb0SiLZnb+W382byr+nqYbYCvPASu5ifRtM1adwngfcd7w1JbkylzlzuXStFl\n" + + "qpNGKVWPYVwb3I3mCmeppThYWakrvXQcy1VFHJ2LHehoVCQsaf2UxgZVazwV22wG\n" + + "UF7e3grTc2+dsTTIUuF04jLir34N++PE5RufI1irADj4WhdaFI7st1YaWCBZSe5Z\n" + + "UR298IlatrKQ088mfWQc4oHHznRO1ffoHUmmL31uh5O9AgMBAAGjgcMwgcAwDAYD\n" + + "VR0TAQH/BAIwADAdBgNVHQ4EFgQU0Xtr2IIM7Kdw2priuuGKDM9G2WswgYAGA1Ud\n" + + "IwR5MHeAFNF7a9iCDOyncNqa4rrhigzPRtlroUmkRzBFMRAwDgYDVQQKDAdGYW5y\n" + + "dWFuMRUwEwYDVQQLDAxPbmVMb2dpbiBJZFAxGjAYBgNVBAMMEU9uZUxvZ2luIEFj\n" + + "Y291bnQgghQHb/sbSOtdkSlmoI4KUA7D20zSCzAOBgNVHQ8BAf8EBAMCB4AwDQYJ\n" + + "KoZIhvcNAQEFBQADggEBAIJ6vM7/WZ4yELkC5ql3sQCE+NilPSXgksk44ZF+MqNA\n" + + "Cc4KjYbU9eFCKhrzOxXIX4+rw2A/M1EOUpj1T88wKnQtzzwciglao3uvPLP9mUgT\n" + + "KiBqHaHV42piwy9bdwf/yckgZmo0DnwOSO9mhHcrKBVdFMIfh6iojaC34Diex72O\n" + + "bjY3NDw/Lky/+5KCvCX8L7rQJzdB6uksE3ei4gV6wSBxpP/4qOao8BJh9gCUAAUg\n" + + "gSEFbbmB2CiL4p134uUpDfLt6F7aaOQ+K9CLCrVhHFc8+KT/ubotOe6L6REbfowC\n" + + "bsCvmdbnq3JRPuI/jbT8EYk4PRrWnmRQ6G0zdxkFk7U=\n" + + "-----END CERTIFICATE-----\n"; + String issuer = "https://app.onelogin.com/saml/metadata/36c59575-2adb-4fd8-9eb7-c5c93ffbc5fe"; + String sloEndpoint = "https://codingxiaxw.onelogin.com/trust/saml2/http-redirect/slo/3448273"; + boolean turnOn = true; + return new SSOSamlBean(ssoEndpoint, signatureAlg, signatureCrt, issuer, sloEndpoint, registrationId, turnOn, spCrt, spKey); + } + + @Override + public void iss(String registrationId, HttpServletRequest request, HttpServletResponse response) throws Exception { + Saml2Settings settings = getConfig(getSamlSpConfig(registrationId)); + Auth auth = new Auth(settings, request, response); + String relayState = StringUtils.EMPTY; + // 获取IDP和 重定向内容 + String url = auth.login(relayState, new AuthnRequestParams(false, false, false), true); + response.setStatus(302); + response.setHeader("Location", url); + } +} diff --git a/src/main/java/com/fanruan/sso/utils/OpenSAMLUtils.java b/src/main/java/com/fanruan/hihidata/sso/utils/OpenSAMLUtils.java similarity index 88% rename from src/main/java/com/fanruan/sso/utils/OpenSAMLUtils.java rename to src/main/java/com/fanruan/hihidata/sso/utils/OpenSAMLUtils.java index dc7325d..15c929f 100644 --- a/src/main/java/com/fanruan/sso/utils/OpenSAMLUtils.java +++ b/src/main/java/com/fanruan/hihidata/sso/utils/OpenSAMLUtils.java @@ -1,4 +1,4 @@ -package com.fanruan.sso.utils; +package com.fanruan.hihidata.sso.utils; import javax.servlet.http.HttpServletRequest; @@ -17,8 +17,8 @@ public class OpenSAMLUtils { //设置向浏览器端传送的文件格式 response.setContentType("application/octet-stream;charset=utf-8"); response.setCharacterEncoding("utf-8"); - Browser browser = Browser.resolve(request); - fileName = browser.getEncodedFileName4Download(fileName); +// Browser browser = Browser.resolve(request); +// fileName = browser.getEncodedFileName4Download(fileName); response.setHeader("Content-disposition", "attachment; filename=" + fileName); try (OutputStream out = response.getOutputStream(); BufferedInputStream inp = new BufferedInputStream(new ByteArrayInputStream(content.getBytes("utf-8")));) { int len = 0; diff --git a/src/main/java/com/fanruan/sso/utils/XMLAnalysisUtils.java b/src/main/java/com/fanruan/hihidata/sso/utils/XMLAnalysisUtils.java similarity index 91% rename from src/main/java/com/fanruan/sso/utils/XMLAnalysisUtils.java rename to src/main/java/com/fanruan/hihidata/sso/utils/XMLAnalysisUtils.java index 6edbc6b..3b41f67 100644 --- a/src/main/java/com/fanruan/sso/utils/XMLAnalysisUtils.java +++ b/src/main/java/com/fanruan/hihidata/sso/utils/XMLAnalysisUtils.java @@ -1,11 +1,20 @@ -package com.fanruan.sso.utils; +package com.fanruan.hihidata.sso.utils; import org.apache.commons.lang3.StringUtils; +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.DocumentHelper; +import org.dom4j.Element; import java.util.List; import java.util.Objects; +/** + * @author: codingXiaxw + * @version: 3.7.7 + * Created by codingXiaxw on 2024/8/2 + */ public class XMLAnalysisUtils { private static final String ASSERTION_NODE = "Assertion"; @@ -33,7 +42,6 @@ public class XMLAnalysisUtils { Element element = (Element) ele; if (StringUtils.equals(MEMBER_NAME_NODE.toLowerCase(), element.attributeValue(MATCHING_PARAMETER_NAME).toLowerCase())) { String memberName = element.element(ATTRIBUTE_VALUE_NODE).getText(); - FineLoggerFactory.getLogger().info("The parsed member name is[{}]", memberName); return memberName; } } @@ -54,7 +62,6 @@ public class XMLAnalysisUtils { Element element = (Element) ele; if (StringUtils.equals(MOBILE_NODE.toLowerCase(), element.attributeValue(MATCHING_PARAMETER_NAME).toLowerCase())) { String mobile = element.element(ATTRIBUTE_VALUE_NODE).getText(); - FineLoggerFactory.getLogger().info("The parsed mobile is[{}]", mobile); return mobile; } } @@ -75,7 +82,6 @@ public class XMLAnalysisUtils { Element element = (Element) ele; if (StringUtils.equals(CORP_ID_NODE.toLowerCase(), element.attributeValue(MATCHING_PARAMETER_NAME).toLowerCase())) { String corpId = element.element(ATTRIBUTE_VALUE_NODE).getText(); - FineLoggerFactory.getLogger().info("The parsed corpId is[{}]", corpId); return corpId; } } @@ -93,12 +99,10 @@ public class XMLAnalysisUtils { Element nameElement = subjectElement.element(NAME_ID_NODE); String nameID = nameElement.getText(); if (StringUtils.isNotEmpty(nameID)) { - FineLoggerFactory.getLogger().info("The parsed username is[{}]", nameID); return nameID; } } throw new UnsupportedOperationException("Can not get NameID!"); -// return userName; } } diff --git a/src/main/java/com/fanruan/sso/service/impl/SSOServiceImpl.java b/src/main/java/com/fanruan/sso/service/impl/SSOServiceImpl.java deleted file mode 100644 index 751b8f6..0000000 --- a/src/main/java/com/fanruan/sso/service/impl/SSOServiceImpl.java +++ /dev/null @@ -1,172 +0,0 @@ -package com.fanruan.sso.service.impl; - -import com.fanruan.sso.bean.SSOSamlBean; -import com.fanruan.sso.service.SSOService; -import com.fanruan.sso.utils.XMLAnalysisUtils; -import com.fasterxml.jackson.databind.JsonNode; -import com.onelogin.saml2.Auth; -import com.onelogin.saml2.authn.AuthnRequestParams; -import com.onelogin.saml2.logout.LogoutRequestParams; -import com.onelogin.saml2.settings.Saml2Settings; -import com.onelogin.saml2.settings.SettingsBuilder; -import com.onelogin.saml2.util.Util; -import org.apache.commons.lang3.RandomUtils; -import org.apache.commons.lang3.StringUtils; -import org.springframework.stereotype.Service; -import org.springframework.web.util.WebUtils; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.security.PrivateKey; -import java.security.cert.X509Certificate; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; - - -@Service -public class SSOServiceImpl implements SSOService { - - private static final String UPPERCASE_RULER = "uppercase"; - private static final String LOWERCASE_RULER = "lowercase"; - private static final String RELAY_STATE = "RelayState"; - - @Override - public String generateSpMetadata(String registrationId) throws Exception { - Saml2Settings settings = getConfig(getSamlSpConfig(registrationId)); - settings.setSPValidationOnly(true); - String metadata = settings.getSPMetadata(); - List errors = Saml2Settings.validateMetadata(metadata); - if (errors.isEmpty()) { - return metadata; - } else { - StringBuilder errorsBuilder = new StringBuilder(); - for (String error : errors) { - errorsBuilder.append(error); - } - return errorsBuilder.toString(); - } - } - - @Override - public void slo(String registrationId, HttpServletRequest req, HttpServletResponse res) throws Exception { - Saml2Settings settings = getConfig(getSamlSpConfig(registrationId)); - Auth auth = new Auth(settings, req, res); - auth.processSLO(); - LoginService.getInstance().crossDomainLogout(req, res, "callback").createCrossDomainResponse(); - auth.logout(); - } - - @Override - public String logout(String registrationId, HttpServletRequest req, HttpServletResponse res) throws Exception { - Saml2Settings settings = getConfig(getSamlSpConfig(registrationId)); - Auth auth = new Auth(settings, req, res); - return auth.logout(StringUtils.EMPTY, new LogoutRequestParams(), true); - } - - @Override - public String acs(String registrationId, HttpServletRequest request, HttpServletResponse response) throws Exception { - Saml2Settings settings = getConfig(getSamlSpConfig(registrationId)); - Auth auth = new Auth(settings, request, response); - auth.processResponse(); - String lastResponseXML = auth.getLastResponseXML(); - FineLoggerFactory.getLogger().info("registrationId is {}, The xml is: {}", registrationId, lastResponseXML); - - // 先校验下responese的合法性 - // String username = XMLAnalysisUtils.getUserName(lastResponseXML); - String memberName = XMLAnalysisUtils.getMemberName(lastResponseXML); - String corpId = XMLAnalysisUtils.getCorpId(lastResponseXML); - String relayState = WebUtils.getHTTPRequestParameter(request, RELAY_STATE); - if (Objects.isNull(user)) { - // 走注册逻辑 - String newUserId = RandomUtils.generateUUIDString(); - User newUser = corpCell.initDecisionMember(newUserId, mobile); - return ssoLogin(corpService, request, response, newUser, corpId, relayState, registrationId); - } - return ssoLogin(corpService, request, response, user, corpId, relayState, registrationId); - } - - @NotNull - private String ssoLogin(CorpService corpService, HttpServletRequest request, HttpServletResponse response, User newUser, String corpId, - String relayState, String registrationId) throws Exception { - corpService.reLogin(request, response, newUser, corpId); - String serviceUrl = TemplateUtils.renderParameter4Tpl(HiCommonConstants.MAIN_PAGE_HOME, HiServletURLProvider.getServletUrlMap()); - String loginUrl = TemplateUtils.renderParameter4Tpl(HiCommonConstants.LOCAL_LOGIN, HiServletURLProvider.getServletUrlMap()); - request.getSession().setAttribute(IdApiConstants.SSO_LOGIN, registrationId); - if (StringUtils.isNotEmpty(relayState)) { - response.sendRedirect(serviceUrl); - return StringUtils.EMPTY; - } - response.sendRedirect(loginUrl); - return StringUtils.EMPTY; - } - - public Saml2Settings getConfig(SSOSamlBean ssoSamlBean) throws Exception { - Map samlData = new HashMap<>(); - - String prefix = TemplateUtils.renderParameter4Tpl(HiCommonConstants.MAIN_PAGE_URL, HiServletURLProvider.getServletUrlMap()); - String spAcsUrl = OemContext.getFullDomain() + prefix + "/sso/saml/" + ssoSamlBean.getRegistrationId() + "/acs"; - String spEntityId = OemContext.getFullDomain() + prefix + "/sso/saml/" + ssoSamlBean.getRegistrationId() + "/iss"; - samlData.put("onelogin.saml2.sp.entityid", spEntityId); - samlData.put("onelogin.saml2.sp.assertion_consumer_service.url", spAcsUrl); - - //IDP配置 - String idpEntityId = ssoSamlBean.getIssuer(); - String idpSignInUrl = ssoSamlBean.getSsoEndpoint(); - String idpPublicKey = ssoSamlBean.getSignatureCrt(); - String idpLogOutUrl = ssoSamlBean.getSloEndpoint(); - - samlData.put("onelogin.saml2.idp.single_sign_on_service.url", idpSignInUrl); - samlData.put("onelogin.saml2.idp.entityid", idpEntityId); - X509Certificate idpX509CertInstance = Util.loadCert((idpPublicKey).trim()); - samlData.put("onelogin.saml2.idp.x509cert", idpX509CertInstance); - - String cert = ssoSamlBean.getSpCrt(); - X509Certificate spX509CertInstance = Util.loadCert(cert.trim()); - samlData.put("onelogin.saml2.sp.x509cert", spX509CertInstance); - - String privateKey = ssoSamlBean.getSpPrivateKey(); - PrivateKey spPrivateKey = Util.loadPrivateKey(privateKey.trim()); - samlData.put("onelogin.saml2.sp.privatekey", spPrivateKey); - - samlData.put("onelogin.saml2.security.authnrequest_signed", true); - samlData.put("onelogin.saml2.security.logoutrequest_signed", true); - //签名断言和加密断言的功能都默认开启了,增加安全性 - samlData.put("onelogin.saml2.security.want_assertions_signed", true); - samlData.put("onelogin.saml2.security.want_assertions_encrypted", true); - samlData.put("onelogin.saml2.security.want_nameid_encrypted", true); - samlData.put("onelogin.saml2.idp.single_logout_service.url", idpLogOutUrl); - - SettingsBuilder builder = new SettingsBuilder(); - Saml2Settings settings = builder.fromValues(samlData).build(); - - return settings; - } - - @Override - public SSOSamlBean getSamlSpConfig(String registrationId) throws Exception { - JsonNode jsonNode = oemService.find(registrationId); - String spCrt = OemContext.getValue(jsonNode, OemContext.CRT_TEXT); - String spKey = OemContext.getValue(jsonNode, OemContext.KEY_TEXT); - - JsonNode ssoConfig = jsonNode.get(OemContext.SSO); - String ssoEndpoint = OemContext.getValue(ssoConfig, OemContext.SSO_ENDPOINT); - String signatureAlg = OemContext.getValue(ssoConfig, OemContext.SSO_SIG_ALG); - String signatureCrt = OemContext.getValue(ssoConfig, OemContext.SSO_SIG_CRT); - String issuer = OemContext.getValue(ssoConfig, OemContext.SSO_ISSUER); - String sloEndpoint = OemContext.getValue(ssoConfig, OemContext.SLO_ENDPOINT); - boolean turnOn = ssoConfig.get("turnOn").asBoolean(); - return new SSOSamlBean(ssoEndpoint, signatureAlg, signatureCrt, issuer, sloEndpoint, registrationId, turnOn, spCrt, spKey); - } - - @Override - public void iss(String registrationId, HttpServletRequest request, HttpServletResponse response) throws Exception { - Saml2Settings settings = getConfig(getSamlSpConfig(registrationId)); - Auth auth = new Auth(settings, request, response); - // 获取IDP和 重定向内容 - String url = auth.login(WebUtils.getOriginalURL(request), new AuthnRequestParams(false, false, false), true); - response.setStatus(302); - response.setHeader("Location", url); - } -}