commit
52d4c1c586
15 changed files with 796 additions and 0 deletions
@ -0,0 +1,8 @@ |
|||||||
|
# Default ignored files |
||||||
|
/shelf/ |
||||||
|
/workspace.xml |
||||||
|
# Editor-based HTTP Client requests |
||||||
|
/httpRequests/ |
||||||
|
# Datasource local storage ignored files |
||||||
|
/dataSources/ |
||||||
|
/dataSources.local.xml |
@ -0,0 +1,30 @@ |
|||||||
|
buildscript { |
||||||
|
ext { |
||||||
|
springBootVersion = '2.5.14' |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
plugins { |
||||||
|
id 'java' |
||||||
|
} |
||||||
|
|
||||||
|
group 'org.example' |
||||||
|
version '1.0-SNAPSHOT' |
||||||
|
|
||||||
|
repositories { |
||||||
|
mavenCentral() |
||||||
|
} |
||||||
|
|
||||||
|
dependencies { |
||||||
|
|
||||||
|
implementation 'com.onelogin:java-saml:2.9.0' |
||||||
|
implementation(platform("org.springframework.boot:spring-boot-dependencies:" + springBootVersion)) |
||||||
|
implementation 'org.springframework.boot:spring-boot-starter-web' |
||||||
|
|
||||||
|
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.2' |
||||||
|
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.2' |
||||||
|
} |
||||||
|
|
||||||
|
test { |
||||||
|
useJUnitPlatform() |
||||||
|
} |
@ -0,0 +1,5 @@ |
|||||||
|
distributionBase=GRADLE_USER_HOME |
||||||
|
distributionPath=wrapper/dists |
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.1-bin.zip |
||||||
|
zipStoreBase=GRADLE_USER_HOME |
||||||
|
zipStorePath=wrapper/dists |
@ -0,0 +1,39 @@ |
|||||||
|
<?xml version="1.0"?> |
||||||
|
<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata" entityID="https://app.onelogin.com/saml/metadata/0110a1e6-c349-45c4-9728-310cb79d843d"> |
||||||
|
<IDPSSODescriptor xmlns:ds="http://www.w3.org/2000/09/xmldsig#" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"> |
||||||
|
<KeyDescriptor use="signing"> |
||||||
|
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> |
||||||
|
<ds:X509Data> |
||||||
|
<ds:X509Certificate>MIID3DCCAsSgAwIBAgIUB2/7G0jrXZEpZqCOClAOw9tM0gswDQYJKoZIhvcNAQEF |
||||||
|
BQAwRTEQMA4GA1UECgwHRmFucnVhbjEVMBMGA1UECwwMT25lTG9naW4gSWRQMRow |
||||||
|
GAYDVQQDDBFPbmVMb2dpbiBBY2NvdW50IDAeFw0yNDA4MDEwMzM3MzZaFw0yOTA4 |
||||||
|
MDEwMzM3MzZaMEUxEDAOBgNVBAoMB0ZhbnJ1YW4xFTATBgNVBAsMDE9uZUxvZ2lu |
||||||
|
IElkUDEaMBgGA1UEAwwRT25lTG9naW4gQWNjb3VudCAwggEiMA0GCSqGSIb3DQEB |
||||||
|
AQUAA4IBDwAwggEKAoIBAQCWV9aev80yVah8cbhq3JYSn30GiJQFXPXX09zPzztO |
||||||
|
FcvnKsskx5oRj0DXVuhGwPEaQ4b2wMahMNHoGVVuMFAs1xPa55lxcY4XirEhY/nW |
||||||
|
i9CYb0SiLZnb+W382byr+nqYbYCvPASu5ifRtM1adwngfcd7w1JbkylzlzuXStFl |
||||||
|
qpNGKVWPYVwb3I3mCmeppThYWakrvXQcy1VFHJ2LHehoVCQsaf2UxgZVazwV22wG |
||||||
|
UF7e3grTc2+dsTTIUuF04jLir34N++PE5RufI1irADj4WhdaFI7st1YaWCBZSe5Z |
||||||
|
UR298IlatrKQ088mfWQc4oHHznRO1ffoHUmmL31uh5O9AgMBAAGjgcMwgcAwDAYD |
||||||
|
VR0TAQH/BAIwADAdBgNVHQ4EFgQU0Xtr2IIM7Kdw2priuuGKDM9G2WswgYAGA1Ud |
||||||
|
IwR5MHeAFNF7a9iCDOyncNqa4rrhigzPRtlroUmkRzBFMRAwDgYDVQQKDAdGYW5y |
||||||
|
dWFuMRUwEwYDVQQLDAxPbmVMb2dpbiBJZFAxGjAYBgNVBAMMEU9uZUxvZ2luIEFj |
||||||
|
Y291bnQgghQHb/sbSOtdkSlmoI4KUA7D20zSCzAOBgNVHQ8BAf8EBAMCB4AwDQYJ |
||||||
|
KoZIhvcNAQEFBQADggEBAIJ6vM7/WZ4yELkC5ql3sQCE+NilPSXgksk44ZF+MqNA |
||||||
|
Cc4KjYbU9eFCKhrzOxXIX4+rw2A/M1EOUpj1T88wKnQtzzwciglao3uvPLP9mUgT |
||||||
|
KiBqHaHV42piwy9bdwf/yckgZmo0DnwOSO9mhHcrKBVdFMIfh6iojaC34Diex72O |
||||||
|
bjY3NDw/Lky/+5KCvCX8L7rQJzdB6uksE3ei4gV6wSBxpP/4qOao8BJh9gCUAAUg |
||||||
|
gSEFbbmB2CiL4p134uUpDfLt6F7aaOQ+K9CLCrVhHFc8+KT/ubotOe6L6REbfowC |
||||||
|
bsCvmdbnq3JRPuI/jbT8EYk4PRrWnmRQ6G0zdxkFk7U=</ds:X509Certificate> |
||||||
|
</ds:X509Data> |
||||||
|
</ds:KeyInfo> |
||||||
|
</KeyDescriptor> |
||||||
|
<SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://codingxiaxw.onelogin.com/trust/saml2/http-redirect/slo/3440964"/> |
||||||
|
|
||||||
|
<NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</NameIDFormat> |
||||||
|
|
||||||
|
<SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://codingxiaxw.onelogin.com/trust/saml2/http-redirect/sso/0110a1e6-c349-45c4-9728-310cb79d843d"/> |
||||||
|
<SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://codingxiaxw.onelogin.com/trust/saml2/http-post/sso/0110a1e6-c349-45c4-9728-310cb79d843d"/> |
||||||
|
<SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="https://codingxiaxw.onelogin.com/trust/saml2/soap/sso/0110a1e6-c349-45c4-9728-310cb79d843d"/> |
||||||
|
</IDPSSODescriptor> |
||||||
|
</EntityDescriptor> |
@ -0,0 +1,21 @@ |
|||||||
|
-----BEGIN CERTIFICATE----- |
||||||
|
MIIDcDCCAlgCCQDVWvep1uXiejANBgkqhkiG9w0BAQsFADB6MUUwQwYDVQQIDDxv |
||||||
|
cGVuc3NsIHJlcSAtbmV3IC1rZXkgcnAtcHJpdmF0ZS5rZXkgLW91dCBycC1jZXJ0 |
||||||
|
aWZpY2F0ZS5jc3IxDTALBgNVBAcMBHd1eGkxEDAOBgNVBAoMB2ZhbnJ1YW4xEDAO |
||||||
|
BgNVBAsMB2ZhbnJ1YW4wHhcNMjQwODA4MTEyNjIzWhcNMjUwODA4MTEyNjIzWjB6 |
||||||
|
MUUwQwYDVQQIDDxvcGVuc3NsIHJlcSAtbmV3IC1rZXkgcnAtcHJpdmF0ZS5rZXkg |
||||||
|
LW91dCBycC1jZXJ0aWZpY2F0ZS5jc3IxDTALBgNVBAcMBHd1eGkxEDAOBgNVBAoM |
||||||
|
B2ZhbnJ1YW4xEDAOBgNVBAsMB2ZhbnJ1YW4wggEiMA0GCSqGSIb3DQEBAQUAA4IB |
||||||
|
DwAwggEKAoIBAQDS0iT7OyG3Y1+3mLfXeoAFZLgiwUel143W5gdlbXSHbuJ0xNrE |
||||||
|
vaGRaUj0vZCdVPL6bAtQiJGQGAEgYpp9ZeaPexCrOE92LhHGZADbcVT2B954ni+f |
||||||
|
LKG7J9FnZcRDOBEqYhyVqTvG6uN0TIIkRwKFTjsSPdRQyqV6uNW4y+r8RrjIOAMS |
||||||
|
K5CWKZbqiiAcb5EqmeYQfWNLjVCn+E199R1LIlEnrMz4+kHEIOTTzNQht30utx5f |
||||||
|
aiBlLQ9XVyVPWHV0iNzGs2qxHUA07bZyEuiG2t+79OAQWKzjqTK5GTvAWEbZ6IaO |
||||||
|
FVi970pG7E14T+rivZGqJrLWvv8MvW4BE0v7AgMBAAEwDQYJKoZIhvcNAQELBQAD |
||||||
|
ggEBAFAZg0TGNSpnIKR1MW4Y0K+2LyslBlMTirrQY21MobS/S+WM8QE+qZvyPUpp |
||||||
|
ilaXnquCptM1MtX/9kPRlRA5v8bEWNZQA6bs3RkH5FC5j+TKcrPti7yAaTcMxw7h |
||||||
|
S/e9e3HZ9ZeU2b1M87Gs1uGTWJ4LyH5vKfHRpNlhOj+rv4k8UeCce/ER0z4OBmwE |
||||||
|
0OtY7xWEP5arF6iVyntpYPbxujuxui1orfsUl5DEOUvKA3VHG5fsgUkhP/KoxFTS |
||||||
|
6ETrC5qy7HCk9J88HX9ovxY/bj/SWwAGx3wNaG+NZz2pQyD6NaBOSRvBC2ZwFlWr |
||||||
|
TgtYc4URcnVH2DOkamR9hFecVA4= |
||||||
|
-----END CERTIFICATE----- |
@ -0,0 +1,27 @@ |
|||||||
|
-----BEGIN RSA PRIVATE KEY----- |
||||||
|
MIIEpAIBAAKCAQEA0tIk+zsht2Nft5i313qABWS4IsFHpdeN1uYHZW10h27idMTa |
||||||
|
xL2hkWlI9L2QnVTy+mwLUIiRkBgBIGKafWXmj3sQqzhPdi4RxmQA23FU9gfeeJ4v |
||||||
|
nyyhuyfRZ2XEQzgRKmIclak7xurjdEyCJEcChU47Ej3UUMqlerjVuMvq/Ea4yDgD |
||||||
|
EiuQlimW6oogHG+RKpnmEH1jS41Qp/hNffUdSyJRJ6zM+PpBxCDk08zUIbd9Lrce |
||||||
|
X2ogZS0PV1clT1h1dIjcxrNqsR1ANO22chLohtrfu/TgEFis46kyuRk7wFhG2eiG |
||||||
|
jhVYve9KRuxNeE/q4r2Rqiay1r7/DL1uARNL+wIDAQABAoIBAFq4h6V8+rNaFhSB |
||||||
|
qYsWcgTgJMT/+38IVUdG0aP6CA1H0DeDhsjm+aIDdpuq/5JUvgK5f9z2B/3D9qgj |
||||||
|
Bmwz75WK1c94eelXRdrjqeLE0FTXagrpt4B9ylMpfVlLV7u9YtWkRry4iLq+1YZ0 |
||||||
|
bgSCcjk/QvhElxr1OWSoKYBOcB6C39o96Obzek6cgdUNRZpP1pnyNpYMAnrHUOnR |
||||||
|
a+iFMFt3q7Pn815EG4Rg4Emgmd9v9c/xAonrqoXddZSsCfUTo1duqfoxJnU21O3q |
||||||
|
spcofbX25sULYL1gpM4p1V92hHaSNZHdZhxMlUuSCwBk1PJEGLrFEDiVZXXDcH8m |
||||||
|
B8ghZrECgYEA/H/gz0rkNW6zk1nMKT/ozJUb0XqTVZBrJuq7L0vmOUuNUMalbkzA |
||||||
|
GlDUM7r852yeiwx4S+XgTRvWRsqau/cuX1B+Z4qaLjWi7RUrQqI9iZS3HFbdX21R |
||||||
|
pXz03iCPONL+X4Mzh6Z7NIKf8ptn4syMXJan1M5XrsM8bPAS1oRyuf8CgYEA1b5Z |
||||||
|
Pkzk6N6GqGVzfNQ8G3l4620rbJBvc1itNTK4TX1W9MOKIHj/zoYopgk+2snQQtUd |
||||||
|
2Urg+3LzJ7vegBmt8Mlpjs6Y27Iz4gyurWHAYEkBK/weqExOz6QB1lYFaO3DPHcx |
||||||
|
+SJc2tSmoBEvcLmEBfvJ0uIvN637BmyPg7umVgUCgYEAgwV8SzRqXMuXxTNIfHMc |
||||||
|
QuRwre9z+mdZIrWU8gLpcPuiVbLubuDGoiElK76wswmq7y5GUePz0y9Jriw9xKGL |
||||||
|
34uuO94xCR9t7qYYb5guZHDV34+3iWf5gOzpR0YP64WY10kGeTJLJkFN7B719jr7 |
||||||
|
7qOCbSuxVg8bENA2hjfuLFMCgYEAp60PrYP8/4Gx+WC83GxSSutcJLQboKseA0rJ |
||||||
|
djY3xvJQyOqs7RR++LDeKoKOQGyZaBRvugq3vApNHhqPTcbXYVFf8Zu45oBBm09/ |
||||||
|
qJxKoj4jITJDiptyKAntNwt8avg6dLC9D0gZt8GihWd14+Rk4ZzIkxrFF9TwW/XG |
||||||
|
D/2hW1ECgYBQtU5PYiaMb7zTVQVVS7aVbym6QInvyZ03O64Y3y+cLf+PFG3F6q/4 |
||||||
|
SRtsmILe+sBY8MdQj0gvGBguMRTgprahS38mbQLdyGCmJIsKdqk9IHv4xU9sHU+n |
||||||
|
xoznawU1UDlxxWrfBpaYVb4CkxaDjL5FvWHv74ZgZ1+Zh3e0gCuIzQ== |
||||||
|
-----END RSA PRIVATE KEY----- |
@ -0,0 +1,39 @@ |
|||||||
|
<?xml version="1.0"?><md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" validUntil="2024-08-11T07:38:28Z" cacheDuration="PT604800S" entityID="http://localhost:8081/decision/sso/saml/coding/iss" ID="ONELOGIN_82622fcf-63a5-4d42-83af-1358c5f5e6fa"><md:SPSSODescriptor AuthnRequestsSigned="true" WantAssertionsSigned="true" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"><md:KeyDescriptor use="signing"><ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:X509Data><ds:X509Certificate>MIIDcDCCAlgCCQDVWvep1uXiejANBgkqhkiG9w0BAQsFADB6MUUwQwYDVQQIDDxv |
||||||
|
cGVuc3NsIHJlcSAtbmV3IC1rZXkgcnAtcHJpdmF0ZS5rZXkgLW91dCBycC1jZXJ0 |
||||||
|
aWZpY2F0ZS5jc3IxDTALBgNVBAcMBHd1eGkxEDAOBgNVBAoMB2ZhbnJ1YW4xEDAO |
||||||
|
BgNVBAsMB2ZhbnJ1YW4wHhcNMjQwODA4MTEyNjIzWhcNMjUwODA4MTEyNjIzWjB6 |
||||||
|
MUUwQwYDVQQIDDxvcGVuc3NsIHJlcSAtbmV3IC1rZXkgcnAtcHJpdmF0ZS5rZXkg |
||||||
|
LW91dCBycC1jZXJ0aWZpY2F0ZS5jc3IxDTALBgNVBAcMBHd1eGkxEDAOBgNVBAoM |
||||||
|
B2ZhbnJ1YW4xEDAOBgNVBAsMB2ZhbnJ1YW4wggEiMA0GCSqGSIb3DQEBAQUAA4IB |
||||||
|
DwAwggEKAoIBAQDS0iT7OyG3Y1+3mLfXeoAFZLgiwUel143W5gdlbXSHbuJ0xNrE |
||||||
|
vaGRaUj0vZCdVPL6bAtQiJGQGAEgYpp9ZeaPexCrOE92LhHGZADbcVT2B954ni+f |
||||||
|
LKG7J9FnZcRDOBEqYhyVqTvG6uN0TIIkRwKFTjsSPdRQyqV6uNW4y+r8RrjIOAMS |
||||||
|
K5CWKZbqiiAcb5EqmeYQfWNLjVCn+E199R1LIlEnrMz4+kHEIOTTzNQht30utx5f |
||||||
|
aiBlLQ9XVyVPWHV0iNzGs2qxHUA07bZyEuiG2t+79OAQWKzjqTK5GTvAWEbZ6IaO |
||||||
|
FVi970pG7E14T+rivZGqJrLWvv8MvW4BE0v7AgMBAAEwDQYJKoZIhvcNAQELBQAD |
||||||
|
ggEBAFAZg0TGNSpnIKR1MW4Y0K+2LyslBlMTirrQY21MobS/S+WM8QE+qZvyPUpp |
||||||
|
ilaXnquCptM1MtX/9kPRlRA5v8bEWNZQA6bs3RkH5FC5j+TKcrPti7yAaTcMxw7h |
||||||
|
S/e9e3HZ9ZeU2b1M87Gs1uGTWJ4LyH5vKfHRpNlhOj+rv4k8UeCce/ER0z4OBmwE |
||||||
|
0OtY7xWEP5arF6iVyntpYPbxujuxui1orfsUl5DEOUvKA3VHG5fsgUkhP/KoxFTS |
||||||
|
6ETrC5qy7HCk9J88HX9ovxY/bj/SWwAGx3wNaG+NZz2pQyD6NaBOSRvBC2ZwFlWr |
||||||
|
TgtYc4URcnVH2DOkamR9hFecVA4= |
||||||
|
</ds:X509Certificate></ds:X509Data></ds:KeyInfo></md:KeyDescriptor><md:KeyDescriptor use="encryption"><ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:X509Data><ds:X509Certificate>MIIDcDCCAlgCCQDVWvep1uXiejANBgkqhkiG9w0BAQsFADB6MUUwQwYDVQQIDDxv |
||||||
|
cGVuc3NsIHJlcSAtbmV3IC1rZXkgcnAtcHJpdmF0ZS5rZXkgLW91dCBycC1jZXJ0 |
||||||
|
aWZpY2F0ZS5jc3IxDTALBgNVBAcMBHd1eGkxEDAOBgNVBAoMB2ZhbnJ1YW4xEDAO |
||||||
|
BgNVBAsMB2ZhbnJ1YW4wHhcNMjQwODA4MTEyNjIzWhcNMjUwODA4MTEyNjIzWjB6 |
||||||
|
MUUwQwYDVQQIDDxvcGVuc3NsIHJlcSAtbmV3IC1rZXkgcnAtcHJpdmF0ZS5rZXkg |
||||||
|
LW91dCBycC1jZXJ0aWZpY2F0ZS5jc3IxDTALBgNVBAcMBHd1eGkxEDAOBgNVBAoM |
||||||
|
B2ZhbnJ1YW4xEDAOBgNVBAsMB2ZhbnJ1YW4wggEiMA0GCSqGSIb3DQEBAQUAA4IB |
||||||
|
DwAwggEKAoIBAQDS0iT7OyG3Y1+3mLfXeoAFZLgiwUel143W5gdlbXSHbuJ0xNrE |
||||||
|
vaGRaUj0vZCdVPL6bAtQiJGQGAEgYpp9ZeaPexCrOE92LhHGZADbcVT2B954ni+f |
||||||
|
LKG7J9FnZcRDOBEqYhyVqTvG6uN0TIIkRwKFTjsSPdRQyqV6uNW4y+r8RrjIOAMS |
||||||
|
K5CWKZbqiiAcb5EqmeYQfWNLjVCn+E199R1LIlEnrMz4+kHEIOTTzNQht30utx5f |
||||||
|
aiBlLQ9XVyVPWHV0iNzGs2qxHUA07bZyEuiG2t+79OAQWKzjqTK5GTvAWEbZ6IaO |
||||||
|
FVi970pG7E14T+rivZGqJrLWvv8MvW4BE0v7AgMBAAEwDQYJKoZIhvcNAQELBQAD |
||||||
|
ggEBAFAZg0TGNSpnIKR1MW4Y0K+2LyslBlMTirrQY21MobS/S+WM8QE+qZvyPUpp |
||||||
|
ilaXnquCptM1MtX/9kPRlRA5v8bEWNZQA6bs3RkH5FC5j+TKcrPti7yAaTcMxw7h |
||||||
|
S/e9e3HZ9ZeU2b1M87Gs1uGTWJ4LyH5vKfHRpNlhOj+rv4k8UeCce/ER0z4OBmwE |
||||||
|
0OtY7xWEP5arF6iVyntpYPbxujuxui1orfsUl5DEOUvKA3VHG5fsgUkhP/KoxFTS |
||||||
|
6ETrC5qy7HCk9J88HX9ovxY/bj/SWwAGx3wNaG+NZz2pQyD6NaBOSRvBC2ZwFlWr |
||||||
|
TgtYc4URcnVH2DOkamR9hFecVA4= |
||||||
|
</ds:X509Certificate></ds:X509Data></ds:KeyInfo></md:KeyDescriptor><md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</md:NameIDFormat><md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://localhost:8081/decision/sso/saml/coding/acs" index="1"/></md:SPSSODescriptor></md:EntityDescriptor> |
@ -0,0 +1,142 @@ |
|||||||
|
package com.fanruan.sso.bean; |
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; |
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude; |
||||||
|
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true) |
||||||
|
@JsonInclude(JsonInclude.Include.NON_NULL) |
||||||
|
public class SSOSamlBean { |
||||||
|
|
||||||
|
/** |
||||||
|
* idp endpoint |
||||||
|
*/ |
||||||
|
private String ssoEndpoint; |
||||||
|
|
||||||
|
/** |
||||||
|
* idp算法 |
||||||
|
*/ |
||||||
|
private String signatureAlg; |
||||||
|
|
||||||
|
/** |
||||||
|
* idp公钥 |
||||||
|
*/ |
||||||
|
private String signatureCrt; |
||||||
|
|
||||||
|
/** |
||||||
|
* idp issuer |
||||||
|
*/ |
||||||
|
private String issuer; |
||||||
|
|
||||||
|
/** |
||||||
|
* idp slo |
||||||
|
*/ |
||||||
|
private String sloEndpoint; |
||||||
|
|
||||||
|
/** |
||||||
|
* 是否开启单点登录 |
||||||
|
*/ |
||||||
|
private boolean turnOn; |
||||||
|
|
||||||
|
/** |
||||||
|
* sp 证书 |
||||||
|
*/ |
||||||
|
private String spCrt; |
||||||
|
|
||||||
|
/** |
||||||
|
* sp 私钥 |
||||||
|
*/ |
||||||
|
private String spPrivateKey; |
||||||
|
|
||||||
|
/** |
||||||
|
* 唯一标识, |
||||||
|
* 如果是odm的sso,则为odm的id |
||||||
|
* 如果是企业设置的sso,则为九数云的企业id |
||||||
|
*/ |
||||||
|
private String registrationId; |
||||||
|
|
||||||
|
|
||||||
|
public SSOSamlBean(String ssoEndpoint, String signatureAlg, String signatureCrt, String issuer, String sloEndpoint, |
||||||
|
String registrationId, boolean turnOn, String spCrt, String spPrivateKey) { |
||||||
|
this.ssoEndpoint = ssoEndpoint; |
||||||
|
this.signatureAlg = signatureAlg; |
||||||
|
this.signatureCrt = signatureCrt; |
||||||
|
this.issuer = issuer; |
||||||
|
this.sloEndpoint = sloEndpoint; |
||||||
|
this.registrationId = registrationId; |
||||||
|
this.turnOn = turnOn; |
||||||
|
this.spCrt = spCrt; |
||||||
|
this.spPrivateKey = spPrivateKey; |
||||||
|
} |
||||||
|
|
||||||
|
public String getSpCrt() { |
||||||
|
return spCrt; |
||||||
|
} |
||||||
|
|
||||||
|
public void setSpCrt(String spCrt) { |
||||||
|
this.spCrt = spCrt; |
||||||
|
} |
||||||
|
|
||||||
|
public String getSpPrivateKey() { |
||||||
|
return spPrivateKey; |
||||||
|
} |
||||||
|
|
||||||
|
public void setSpPrivateKey(String spPrivateKey) { |
||||||
|
this.spPrivateKey = spPrivateKey; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isTurnOn() { |
||||||
|
return turnOn; |
||||||
|
} |
||||||
|
|
||||||
|
public void setTurnOn(boolean turnOn) { |
||||||
|
this.turnOn = turnOn; |
||||||
|
} |
||||||
|
|
||||||
|
public String getRegistrationId() { |
||||||
|
return registrationId; |
||||||
|
} |
||||||
|
|
||||||
|
public void setRegistrationId(String registrationId) { |
||||||
|
this.registrationId = registrationId; |
||||||
|
} |
||||||
|
|
||||||
|
public String getSsoEndpoint() { |
||||||
|
return ssoEndpoint; |
||||||
|
} |
||||||
|
|
||||||
|
public void setSsoEndpoint(String ssoEndpoint) { |
||||||
|
this.ssoEndpoint = ssoEndpoint; |
||||||
|
} |
||||||
|
|
||||||
|
public String getSignatureAlg() { |
||||||
|
return signatureAlg; |
||||||
|
} |
||||||
|
|
||||||
|
public void setSignatureAlg(String signatureAlg) { |
||||||
|
this.signatureAlg = signatureAlg; |
||||||
|
} |
||||||
|
|
||||||
|
public String getSignatureCrt() { |
||||||
|
return signatureCrt; |
||||||
|
} |
||||||
|
|
||||||
|
public void setSignatureCrt(String signatureCrt) { |
||||||
|
this.signatureCrt = signatureCrt; |
||||||
|
} |
||||||
|
|
||||||
|
public String getIssuer() { |
||||||
|
return issuer; |
||||||
|
} |
||||||
|
|
||||||
|
public void setIssuer(String issuer) { |
||||||
|
this.issuer = issuer; |
||||||
|
} |
||||||
|
|
||||||
|
public String getSloEndpoint() { |
||||||
|
return sloEndpoint; |
||||||
|
} |
||||||
|
|
||||||
|
public void setSloEndpoint(String sloEndpoint) { |
||||||
|
this.sloEndpoint = sloEndpoint; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,75 @@ |
|||||||
|
package com.fanruan.sso.bean; |
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; |
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude; |
||||||
|
|
||||||
|
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true) |
||||||
|
@JsonInclude(JsonInclude.Include.NON_NULL) |
||||||
|
public class SSOSamlResultBean { |
||||||
|
|
||||||
|
/** |
||||||
|
* sso endpoint |
||||||
|
*/ |
||||||
|
private String ssoEndpoint; |
||||||
|
|
||||||
|
/** |
||||||
|
* sp metadata |
||||||
|
*/ |
||||||
|
private String spMetadata; |
||||||
|
|
||||||
|
/** |
||||||
|
* sp sso地址 |
||||||
|
*/ |
||||||
|
private String spIss; |
||||||
|
|
||||||
|
/** |
||||||
|
* sp 断言消费地址 |
||||||
|
*/ |
||||||
|
private String spAcs; |
||||||
|
|
||||||
|
/** |
||||||
|
* sp 登录地址 |
||||||
|
*/ |
||||||
|
private String spSlo; |
||||||
|
|
||||||
|
public String getSsoEndpoint() { |
||||||
|
return ssoEndpoint; |
||||||
|
} |
||||||
|
|
||||||
|
public void setSsoEndpoint(String ssoEndpoint) { |
||||||
|
this.ssoEndpoint = ssoEndpoint; |
||||||
|
} |
||||||
|
|
||||||
|
public String getSpMetadata() { |
||||||
|
return spMetadata; |
||||||
|
} |
||||||
|
|
||||||
|
public void setSpMetadata(String spMetadata) { |
||||||
|
this.spMetadata = spMetadata; |
||||||
|
} |
||||||
|
|
||||||
|
public String getSpIss() { |
||||||
|
return spIss; |
||||||
|
} |
||||||
|
|
||||||
|
public void setSpIss(String spIss) { |
||||||
|
this.spIss = spIss; |
||||||
|
} |
||||||
|
|
||||||
|
public String getSpAcs() { |
||||||
|
return spAcs; |
||||||
|
} |
||||||
|
|
||||||
|
public void setSpAcs(String spAcs) { |
||||||
|
this.spAcs = spAcs; |
||||||
|
} |
||||||
|
|
||||||
|
public String getSpSlo() { |
||||||
|
return spSlo; |
||||||
|
} |
||||||
|
|
||||||
|
public void setSpSlo(String spSlo) { |
||||||
|
this.spSlo = spSlo; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,59 @@ |
|||||||
|
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; |
||||||
|
import org.apache.commons.lang3.StringUtils; |
||||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||||
|
import org.springframework.http.MediaType; |
||||||
|
import org.springframework.web.bind.annotation.GetMapping; |
||||||
|
import org.springframework.web.bind.annotation.PathVariable; |
||||||
|
import org.springframework.web.bind.annotation.PostMapping; |
||||||
|
import org.springframework.web.bind.annotation.ResponseBody; |
||||||
|
import org.springframework.web.bind.annotation.RestController; |
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest; |
||||||
|
import javax.servlet.http.HttpServletResponse; |
||||||
|
|
||||||
|
@RestController |
||||||
|
public class SSOController { |
||||||
|
|
||||||
|
@Autowired |
||||||
|
private SSOService ssoService; |
||||||
|
|
||||||
|
@ResponseBody |
||||||
|
@GetMapping(value = "/sso/saml/{registrationId}/sp/metadata", produces = MediaType.APPLICATION_XML_VALUE) |
||||||
|
public void getSpMetadata(@PathVariable("registrationId") String registrationId, HttpServletRequest req, HttpServletResponse res) throws Exception { |
||||||
|
String SpMetadata = ssoService.generateSpMetadata(registrationId); |
||||||
|
OpenSAMLUtils.downloadByStringContent(req, res, "sp-metadata.xml", SpMetadata); |
||||||
|
} |
||||||
|
|
||||||
|
@ResponseBody |
||||||
|
@GetMapping(value = "/sso/saml/{registrationId}/iss", produces = MediaType.TEXT_HTML_VALUE) |
||||||
|
public String iss(@PathVariable("registrationId") String registrationId, HttpServletRequest req, HttpServletResponse res) throws Exception { |
||||||
|
ssoService.iss(registrationId, req, res); |
||||||
|
return StringUtils.EMPTY; |
||||||
|
} |
||||||
|
|
||||||
|
@ResponseBody |
||||||
|
@PostMapping(value = "/sso/saml/{registrationId}/acs") |
||||||
|
public String acs(@PathVariable("registrationId") String registrationId, HttpServletRequest req, HttpServletResponse res) throws Exception { |
||||||
|
return ssoService.acs(registrationId, req, res); |
||||||
|
} |
||||||
|
|
||||||
|
@ResponseBody |
||||||
|
@GetMapping(value = "/sso/saml/{registrationId}/slo") |
||||||
|
public String slo(@PathVariable("registrationId") String registrationId, HttpServletRequest req, HttpServletResponse res) throws Exception { |
||||||
|
ssoService.slo(registrationId, req, res); |
||||||
|
return StringUtils.EMPTY; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,20 @@ |
|||||||
|
package com.fanruan.sso.filter; |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import javax.servlet.FilterChain; |
||||||
|
import javax.servlet.ServletException; |
||||||
|
import javax.servlet.http.HttpServletRequest; |
||||||
|
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
|
||||||
|
filterChain.doFilter(req, res); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,22 @@ |
|||||||
|
package com.fanruan.sso.service; |
||||||
|
|
||||||
|
import com.fanruan.hihidata.bean.sso.SSOSamlBean; |
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest; |
||||||
|
import javax.servlet.http.HttpServletResponse; |
||||||
|
|
||||||
|
public interface SSOService { |
||||||
|
|
||||||
|
void iss(String registrationId, HttpServletRequest req, HttpServletResponse res) throws Exception; |
||||||
|
|
||||||
|
String acs(String registrationId, HttpServletRequest req, HttpServletResponse res) throws Exception; |
||||||
|
|
||||||
|
void slo(String registrationId, HttpServletRequest req, HttpServletResponse res) throws Exception; |
||||||
|
|
||||||
|
String logout(String registrationId, HttpServletRequest req, HttpServletResponse res) throws Exception; |
||||||
|
|
||||||
|
String generateSpMetadata(String registrationId) throws Exception; |
||||||
|
|
||||||
|
SSOSamlBean getSamlSpConfig(String registrationId) throws Exception; |
||||||
|
|
||||||
|
} |
@ -0,0 +1,172 @@ |
|||||||
|
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<String> 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<String, Object> 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); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,33 @@ |
|||||||
|
package com.fanruan.sso.utils; |
||||||
|
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest; |
||||||
|
import javax.servlet.http.HttpServletResponse; |
||||||
|
import java.io.BufferedInputStream; |
||||||
|
import java.io.ByteArrayInputStream; |
||||||
|
import java.io.IOException; |
||||||
|
import java.io.OutputStream; |
||||||
|
|
||||||
|
public class OpenSAMLUtils { |
||||||
|
|
||||||
|
public static void downloadByStringContent(HttpServletRequest request, |
||||||
|
HttpServletResponse response, |
||||||
|
String fileName, String content) |
||||||
|
throws IOException { |
||||||
|
//设置向浏览器端传送的文件格式
|
||||||
|
response.setContentType("application/octet-stream;charset=utf-8"); |
||||||
|
response.setCharacterEncoding("utf-8"); |
||||||
|
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; |
||||||
|
byte[] buf = new byte[1024]; |
||||||
|
while ((len = inp.read(buf)) > 0) { |
||||||
|
out.write(buf, 0, len); |
||||||
|
} |
||||||
|
} catch (Exception e) { |
||||||
|
// 输出log
|
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,104 @@ |
|||||||
|
package com.fanruan.sso.utils; |
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
import java.util.Objects; |
||||||
|
|
||||||
|
|
||||||
|
public class XMLAnalysisUtils { |
||||||
|
|
||||||
|
private static final String ASSERTION_NODE = "Assertion"; |
||||||
|
private static final String SUBJECT_NODE = "Subject"; |
||||||
|
private static final String NAME_ID_NODE = "NameID"; |
||||||
|
private static final String MEMBER_NAME_NODE = "MemberName"; |
||||||
|
private static final String MOBILE_NODE = "Mobile"; |
||||||
|
private static final String CORP_ID_NODE = "CorpId"; |
||||||
|
private static final String ATTRIBUTE_STATEMENT_NODE = "AttributeStatement"; |
||||||
|
private static final String ATTRIBUTE_VALUE_NODE = "AttributeValue"; |
||||||
|
private static final String MATCHING_PARAMETER_NAME = "Name"; |
||||||
|
private static final String AUTHN_STATEMENT_NODE = "AuthnStatement"; |
||||||
|
private static final String ATTRIBUTE_SESSION_INDEX = "SessionIndex"; |
||||||
|
public static final String CACHE_SUFFIX = "_@_"; |
||||||
|
|
||||||
|
public static String getMemberName(String xml) throws Exception { |
||||||
|
if (StringUtils.isNotEmpty(xml)) { |
||||||
|
Document doc = DocumentHelper.parseText(xml); |
||||||
|
Element rootElement = doc.getRootElement(); |
||||||
|
Element assertionElement = rootElement.element(ASSERTION_NODE); |
||||||
|
Element statementElement = assertionElement.element(ATTRIBUTE_STATEMENT_NODE); |
||||||
|
if (Objects.nonNull(statementElement)) { |
||||||
|
List list = statementElement.elements(); |
||||||
|
for (Object ele : list) { |
||||||
|
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; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return StringUtils.EMPTY; |
||||||
|
} |
||||||
|
|
||||||
|
public static String getMobile(String xml) throws Exception { |
||||||
|
if (StringUtils.isNotEmpty(xml)) { |
||||||
|
Document doc = DocumentHelper.parseText(xml); |
||||||
|
Element rootElement = doc.getRootElement(); |
||||||
|
Element assertionElement = rootElement.element(ASSERTION_NODE); |
||||||
|
Element statementElement = assertionElement.element(ATTRIBUTE_STATEMENT_NODE); |
||||||
|
if (Objects.nonNull(statementElement)) { |
||||||
|
List list = statementElement.elements(); |
||||||
|
for (Object ele : list) { |
||||||
|
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; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return StringUtils.EMPTY; |
||||||
|
} |
||||||
|
|
||||||
|
public static String getCorpId(String xml) throws Exception { |
||||||
|
if (StringUtils.isNotEmpty(xml)) { |
||||||
|
Document doc = DocumentHelper.parseText(xml); |
||||||
|
Element rootElement = doc.getRootElement(); |
||||||
|
Element assertionElement = rootElement.element(ASSERTION_NODE); |
||||||
|
Element statementElement = assertionElement.element(ATTRIBUTE_STATEMENT_NODE); |
||||||
|
if (Objects.nonNull(statementElement)) { |
||||||
|
List list = statementElement.elements(); |
||||||
|
for (Object ele : list) { |
||||||
|
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; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return StringUtils.EMPTY; |
||||||
|
} |
||||||
|
|
||||||
|
public static String getUserName(String xml) throws DocumentException { |
||||||
|
if (StringUtils.isNotEmpty(xml)) { |
||||||
|
Document doc = DocumentHelper.parseText(xml); |
||||||
|
Element rootElement = doc.getRootElement(); |
||||||
|
Element assertionElement = rootElement.element(ASSERTION_NODE); |
||||||
|
Element subjectElement = assertionElement.element(SUBJECT_NODE); |
||||||
|
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;
|
||||||
|
} |
||||||
|
} |
||||||
|
|
Loading…
Reference in new issue