Date: Sat, 28 Mar 2020 16:48:04 +0530
Subject: [PATCH 038/187] JAVA-623: Moved 3 articles from core-java-security to
security-2
---
.../core-java-security/README.md | 5 +-
core-java-modules/core-java-security/pom.xml | 15 --
.../baeldung/hashing/DigestAlgorithms.java | 9 --
.../baeldung/hashing/Keccak256Hashing.java | 30 ----
.../com/baeldung/hashing/SHA256Hashing.java | 39 -----
.../com/baeldung/hashing/SHA3Hashing.java | 45 ------
.../com/baeldung/hashing/SHACommonUtils.java | 16 --
.../passwordhashing/PBKDF2Hasher.java | 149 ------------------
.../passwordhashing/SHA512Hasher.java | 35 ----
.../passwordhashing/SimplePBKDF2Hasher.java | 18 ---
.../hashing/Keccak256HashingUnitTest.java | 22 ---
.../hashing/SHA256HashingUnitTest.java | 35 ----
.../baeldung/hashing/SHA3HashingUnitTest.java | 38 -----
.../baeldung/java/md5/JavaMD5UnitTest.java | 75 ---------
.../passwordhashing/PBKDF2HasherUnitTest.java | 41 -----
.../passwordhashing/SHA512HasherUnitTest.java | 70 --------
.../src/test/resources/test_md5.txt | 1 -
17 files changed, 2 insertions(+), 641 deletions(-)
delete mode 100644 core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/DigestAlgorithms.java
delete mode 100644 core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/Keccak256Hashing.java
delete mode 100644 core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/SHA256Hashing.java
delete mode 100644 core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/SHA3Hashing.java
delete mode 100644 core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/SHACommonUtils.java
delete mode 100644 core-java-modules/core-java-security/src/main/java/com/baeldung/passwordhashing/PBKDF2Hasher.java
delete mode 100644 core-java-modules/core-java-security/src/main/java/com/baeldung/passwordhashing/SHA512Hasher.java
delete mode 100644 core-java-modules/core-java-security/src/main/java/com/baeldung/passwordhashing/SimplePBKDF2Hasher.java
delete mode 100644 core-java-modules/core-java-security/src/test/java/com/baeldung/hashing/Keccak256HashingUnitTest.java
delete mode 100644 core-java-modules/core-java-security/src/test/java/com/baeldung/hashing/SHA256HashingUnitTest.java
delete mode 100644 core-java-modules/core-java-security/src/test/java/com/baeldung/hashing/SHA3HashingUnitTest.java
delete mode 100644 core-java-modules/core-java-security/src/test/java/com/baeldung/java/md5/JavaMD5UnitTest.java
delete mode 100644 core-java-modules/core-java-security/src/test/java/com/baeldung/passwordhashing/PBKDF2HasherUnitTest.java
delete mode 100644 core-java-modules/core-java-security/src/test/java/com/baeldung/passwordhashing/SHA512HasherUnitTest.java
delete mode 100644 core-java-modules/core-java-security/src/test/resources/test_md5.txt
diff --git a/core-java-modules/core-java-security/README.md b/core-java-modules/core-java-security/README.md
index ff9b1eef14..83b12793b5 100644
--- a/core-java-modules/core-java-security/README.md
+++ b/core-java-modules/core-java-security/README.md
@@ -3,17 +3,16 @@
This module contains articles about core Java Security
### Relevant Articles:
-- [MD5 Hashing in Java](http://www.baeldung.com/java-md5)
+
- [Guide to the Cipher Class](http://www.baeldung.com/java-cipher-class)
- [Introduction to SSL in Java](http://www.baeldung.com/java-ssl)
- [Java KeyStore API](http://www.baeldung.com/java-keystore)
- [Encrypting and Decrypting Files in Java](http://www.baeldung.com/java-cipher-input-output-stream)
-- [Hashing a Password in Java](https://www.baeldung.com/java-password-hashing)
- [SSL Handshake Failures](https://www.baeldung.com/java-ssl-handshake-failures)
-- [SHA-256 and SHA3-256 Hashing in Java](https://www.baeldung.com/sha-256-hashing-java)
- [Enabling TLS v1.2 in Java 7](https://www.baeldung.com/java-7-tls-v12)
- [The Java SecureRandom Class](https://www.baeldung.com/java-secure-random)
- [An Introduction to Java SASL](https://www.baeldung.com/java-sasl)
- [A Guide to Java GSS API](https://www.baeldung.com/java-gss)
- [Intro to the Java SecurityManager](https://www.baeldung.com/java-security-manager)
+- More articles: [[next -->]](/core-java-modules/core-java-security-2)
diff --git a/core-java-modules/core-java-security/pom.xml b/core-java-modules/core-java-security/pom.xml
index a46c2e2d40..96024a73a1 100644
--- a/core-java-modules/core-java-security/pom.xml
+++ b/core-java-modules/core-java-security/pom.xml
@@ -24,24 +24,9 @@
${assertj-core.version}
test
-
-
- commons-codec
- commons-codec
- ${commons-codec.version}
-
-
- org.bouncycastle
- bcprov-jdk15on
- ${bouncycastle.version}
-
-
- 1.60
- 1.11
-
3.10.0
diff --git a/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/DigestAlgorithms.java b/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/DigestAlgorithms.java
deleted file mode 100644
index 94dd22ff4b..0000000000
--- a/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/DigestAlgorithms.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package com.baeldung.hashing;
-
-public class DigestAlgorithms {
-
- public static final String SHA3_256 = "SHA3-256";
- public static final String SHA_256 = "SHA-256";
- public static final String KECCAK_256 = "Keccak-256";
-
-}
diff --git a/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/Keccak256Hashing.java b/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/Keccak256Hashing.java
deleted file mode 100644
index 19fc4cf059..0000000000
--- a/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/Keccak256Hashing.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package com.baeldung.hashing;
-
-import org.bouncycastle.jcajce.provider.digest.Keccak;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.bouncycastle.util.encoders.Hex;
-
-import java.nio.charset.StandardCharsets;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.security.Security;
-
-import static com.baeldung.hashing.DigestAlgorithms.KECCAK_256;
-import static com.baeldung.hashing.SHACommonUtils.bytesToHex;
-
-public class Keccak256Hashing {
-
- public static String hashWithJavaMessageDigest(final String originalString) throws NoSuchAlgorithmException {
- Security.addProvider(new BouncyCastleProvider());
- final MessageDigest digest = MessageDigest.getInstance(KECCAK_256);
- final byte[] encodedhash = digest.digest(originalString.getBytes(StandardCharsets.UTF_8));
- return bytesToHex(encodedhash);
- }
-
- public static String hashWithBouncyCastle(final String originalString) {
- Keccak.Digest256 digest256 = new Keccak.Digest256();
- byte[] hashbytes = digest256.digest(originalString.getBytes(StandardCharsets.UTF_8));
- return new String(Hex.encode(hashbytes));
- }
-
-}
diff --git a/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/SHA256Hashing.java b/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/SHA256Hashing.java
deleted file mode 100644
index ec008cebab..0000000000
--- a/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/SHA256Hashing.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.baeldung.hashing;
-
-import com.google.common.hash.Hashing;
-import org.apache.commons.codec.digest.DigestUtils;
-import org.bouncycastle.util.encoders.Hex;
-
-import java.nio.charset.StandardCharsets;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-
-import static com.baeldung.hashing.DigestAlgorithms.SHA_256;
-import static com.baeldung.hashing.SHACommonUtils.bytesToHex;
-
-public class SHA256Hashing {
-
- public static String HashWithJavaMessageDigest(final String originalString) throws NoSuchAlgorithmException {
- final MessageDigest digest = MessageDigest.getInstance(SHA_256);
- final byte[] encodedhash = digest.digest(originalString.getBytes(StandardCharsets.UTF_8));
- return bytesToHex(encodedhash);
- }
-
- public static String hashWithGuava(final String originalString) {
- final String sha256hex = Hashing.sha256().hashString(originalString, StandardCharsets.UTF_8).toString();
- return sha256hex;
- }
-
- public static String HashWithApacheCommons(final String originalString) {
- final String sha256hex = DigestUtils.sha256Hex(originalString);
- return sha256hex;
- }
-
- public static String HashWithBouncyCastle(final String originalString) throws NoSuchAlgorithmException {
- final MessageDigest digest = MessageDigest.getInstance(SHA_256);
- final byte[] hash = digest.digest(originalString.getBytes(StandardCharsets.UTF_8));
- final String sha256hex = new String(Hex.encode(hash));
- return sha256hex;
- }
-
-}
diff --git a/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/SHA3Hashing.java b/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/SHA3Hashing.java
deleted file mode 100644
index eb363205b1..0000000000
--- a/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/SHA3Hashing.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package com.baeldung.hashing;
-
-import com.google.common.hash.Hashing;
-import org.apache.commons.codec.digest.DigestUtils;
-import org.bouncycastle.crypto.digests.SHA3Digest;
-import org.bouncycastle.jcajce.provider.digest.SHA3;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.bouncycastle.util.encoders.Hex;
-
-import java.nio.charset.StandardCharsets;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.security.Security;
-
-import static com.baeldung.hashing.DigestAlgorithms.SHA3_256;
-import static com.baeldung.hashing.SHACommonUtils.bytesToHex;
-
-public class SHA3Hashing {
-
- /* works with JDK9+ only */
- public static String hashWithJavaMessageDigestJDK9(final String originalString) throws NoSuchAlgorithmException {
- final MessageDigest digest = MessageDigest.getInstance(SHA3_256);
- final byte[] hashbytes = digest.digest(originalString.getBytes(StandardCharsets.UTF_8));
- return bytesToHex(hashbytes);
- }
-
- public static String hashWithJavaMessageDigest(final String originalString) throws NoSuchAlgorithmException {
- Security.addProvider(new BouncyCastleProvider());
- final MessageDigest digest = MessageDigest.getInstance(SHA3_256);
- final byte[] hashbytes = digest.digest(originalString.getBytes(StandardCharsets.UTF_8));
- return bytesToHex(hashbytes);
- }
-
- /* works with JDK9+ only */
- public static String hashWithApacheCommonsJDK9(final String originalString) {
- return new DigestUtils(SHA3_256).digestAsHex(originalString);
- }
-
- public static String hashWithBouncyCastle(final String originalString) {
- SHA3.Digest256 digest256 = new SHA3.Digest256();
- byte[] hashbytes = digest256.digest(originalString.getBytes(StandardCharsets.UTF_8));
- return new String(Hex.encode(hashbytes));
- }
-
-}
diff --git a/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/SHACommonUtils.java b/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/SHACommonUtils.java
deleted file mode 100644
index 0f28408083..0000000000
--- a/core-java-modules/core-java-security/src/main/java/com/baeldung/hashing/SHACommonUtils.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.baeldung.hashing;
-
-class SHACommonUtils {
-
- public static String bytesToHex(byte[] hash) {
- StringBuffer hexString = new StringBuffer();
- for (byte h : hash) {
- String hex = Integer.toHexString(0xff & h);
- if (hex.length() == 1)
- hexString.append('0');
- hexString.append(hex);
- }
- return hexString.toString();
- }
-
-}
diff --git a/core-java-modules/core-java-security/src/main/java/com/baeldung/passwordhashing/PBKDF2Hasher.java b/core-java-modules/core-java-security/src/main/java/com/baeldung/passwordhashing/PBKDF2Hasher.java
deleted file mode 100644
index e2259e4249..0000000000
--- a/core-java-modules/core-java-security/src/main/java/com/baeldung/passwordhashing/PBKDF2Hasher.java
+++ /dev/null
@@ -1,149 +0,0 @@
-package com.baeldung.passwordhashing;
-
-import java.security.NoSuchAlgorithmException;
-import java.security.SecureRandom;
-import java.security.spec.InvalidKeySpecException;
-import java.security.spec.KeySpec;
-import java.util.Arrays;
-import java.util.Base64;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import javax.crypto.SecretKeyFactory;
-import javax.crypto.spec.PBEKeySpec;
-
-/**
- * Hash passwords for storage, and test passwords against password tokens.
- *
- * Instances of this class can be used concurrently by multiple threads.
- *
- * @author erickson
- * @see StackOverflow
- */
-public final class PBKDF2Hasher
-{
-
- /**
- * Each token produced by this class uses this identifier as a prefix.
- */
- public static final String ID = "$31$";
-
- /**
- * The minimum recommended cost, used by default
- */
- public static final int DEFAULT_COST = 16;
-
- private static final String ALGORITHM = "PBKDF2WithHmacSHA1";
-
- private static final int SIZE = 128;
-
- private static final Pattern layout = Pattern.compile("\\$31\\$(\\d\\d?)\\$(.{43})");
-
- private final SecureRandom random;
-
- private final int cost;
-
- public PBKDF2Hasher()
- {
- this(DEFAULT_COST);
- }
-
- /**
- * Create a password manager with a specified cost
- *
- * @param cost the exponential computational cost of hashing a password, 0 to 30
- */
- public PBKDF2Hasher(int cost)
- {
- iterations(cost); /* Validate cost */
- this.cost = cost;
- this.random = new SecureRandom();
- }
-
- private static int iterations(int cost)
- {
- if ((cost < 0) || (cost > 30))
- throw new IllegalArgumentException("cost: " + cost);
- return 1 << cost;
- }
-
- /**
- * Hash a password for storage.
- *
- * @return a secure authentication token to be stored for later authentication
- */
- public String hash(char[] password)
- {
- byte[] salt = new byte[SIZE / 8];
- random.nextBytes(salt);
- byte[] dk = pbkdf2(password, salt, 1 << cost);
- byte[] hash = new byte[salt.length + dk.length];
- System.arraycopy(salt, 0, hash, 0, salt.length);
- System.arraycopy(dk, 0, hash, salt.length, dk.length);
- Base64.Encoder enc = Base64.getUrlEncoder().withoutPadding();
- return ID + cost + '$' + enc.encodeToString(hash);
- }
-
- /**
- * Authenticate with a password and a stored password token.
- *
- * @return true if the password and token match
- */
- public boolean checkPassword(char[] password, String token)
- {
- Matcher m = layout.matcher(token);
- if (!m.matches())
- throw new IllegalArgumentException("Invalid token format");
- int iterations = iterations(Integer.parseInt(m.group(1)));
- byte[] hash = Base64.getUrlDecoder().decode(m.group(2));
- byte[] salt = Arrays.copyOfRange(hash, 0, SIZE / 8);
- byte[] check = pbkdf2(password, salt, iterations);
- int zero = 0;
- for (int idx = 0; idx < check.length; ++idx)
- zero |= hash[salt.length + idx] ^ check[idx];
- return zero == 0;
- }
-
- private static byte[] pbkdf2(char[] password, byte[] salt, int iterations)
- {
- KeySpec spec = new PBEKeySpec(password, salt, iterations, SIZE);
- try {
- SecretKeyFactory f = SecretKeyFactory.getInstance(ALGORITHM);
- return f.generateSecret(spec).getEncoded();
- }
- catch (NoSuchAlgorithmException ex) {
- throw new IllegalStateException("Missing algorithm: " + ALGORITHM, ex);
- }
- catch (InvalidKeySpecException ex) {
- throw new IllegalStateException("Invalid SecretKeyFactory", ex);
- }
- }
-
- /**
- * Hash a password in an immutable {@code String}.
- *
- * Passwords should be stored in a {@code char[]} so that it can be filled
- * with zeros after use instead of lingering on the heap and elsewhere.
- *
- * @deprecated Use {@link #hash(char[])} instead
- */
- @Deprecated
- public String hash(String password)
- {
- return hash(password.toCharArray());
- }
-
- /**
- * Authenticate with a password in an immutable {@code String} and a stored
- * password token.
- *
- * @deprecated Use {@link #checkPassword(char[],String)} instead.
- * @see #hash(String)
- */
- @Deprecated
- public boolean checkPassword(String password, String token)
- {
- return checkPassword(password.toCharArray(), token);
- }
-
-}
diff --git a/core-java-modules/core-java-security/src/main/java/com/baeldung/passwordhashing/SHA512Hasher.java b/core-java-modules/core-java-security/src/main/java/com/baeldung/passwordhashing/SHA512Hasher.java
deleted file mode 100644
index 4f5337f963..0000000000
--- a/core-java-modules/core-java-security/src/main/java/com/baeldung/passwordhashing/SHA512Hasher.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.baeldung.passwordhashing;
-
-import java.nio.charset.StandardCharsets;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-
-
-/** A really simple SHA_512 Encryption example.
- *
- */
-public class SHA512Hasher {
-
- public String hash(String passwordToHash, byte[] salt){
- String generatedPassword = null;
- try {
- MessageDigest md = MessageDigest.getInstance("SHA-512");
- md.update(salt);
- byte[] bytes = md.digest(passwordToHash.getBytes(StandardCharsets.UTF_8));
- StringBuilder sb = new StringBuilder();
- for(int i=0; i< bytes.length ;i++){
- sb.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1));
- }
- generatedPassword = sb.toString();
- }
- catch (NoSuchAlgorithmException e){
- e.printStackTrace();
- }
- return generatedPassword;
- }
-
- public boolean checkPassword(String hash, String attempt, byte[] salt){
- String generatedHash = hash(attempt, salt);
- return hash.equals(generatedHash);
- }
-}
diff --git a/core-java-modules/core-java-security/src/main/java/com/baeldung/passwordhashing/SimplePBKDF2Hasher.java b/core-java-modules/core-java-security/src/main/java/com/baeldung/passwordhashing/SimplePBKDF2Hasher.java
deleted file mode 100644
index 36c9b65070..0000000000
--- a/core-java-modules/core-java-security/src/main/java/com/baeldung/passwordhashing/SimplePBKDF2Hasher.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.baeldung.passwordhashing;
-
-import javax.crypto.SecretKeyFactory;
-import javax.crypto.spec.PBEKeySpec;
-import java.security.spec.KeySpec;
-
-/** A really simple SimplePBKDF2 Encryption example.
- *
- */
-public class SimplePBKDF2Hasher {
-
- public static String hashSimple(String password, byte[] salt) throws Exception{
- KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 65536, 128);
- SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
- byte[] hash = f.generateSecret(spec).getEncoded();
- return String.valueOf(hash);
- }
-}
diff --git a/core-java-modules/core-java-security/src/test/java/com/baeldung/hashing/Keccak256HashingUnitTest.java b/core-java-modules/core-java-security/src/test/java/com/baeldung/hashing/Keccak256HashingUnitTest.java
deleted file mode 100644
index 9ed35c8834..0000000000
--- a/core-java-modules/core-java-security/src/test/java/com/baeldung/hashing/Keccak256HashingUnitTest.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.baeldung.hashing;
-
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-
-public class Keccak256HashingUnitTest {
-
- private static String originalValue = "abc123";
- private static String hashedValue = "719accc61a9cc126830e5906f9d672d06eab6f8597287095a2c55a8b775e7016";
-
- @Test public void testHashWithJavaMessageDigest() throws Exception {
- final String currentHashedValue = Keccak256Hashing.hashWithJavaMessageDigest(originalValue);
- assertEquals(hashedValue, currentHashedValue);
- }
-
- @Test public void testHashWithBouncyCastle() {
- final String currentHashedValue = Keccak256Hashing.hashWithBouncyCastle(originalValue);
- assertEquals(hashedValue, currentHashedValue);
- }
-
-}
diff --git a/core-java-modules/core-java-security/src/test/java/com/baeldung/hashing/SHA256HashingUnitTest.java b/core-java-modules/core-java-security/src/test/java/com/baeldung/hashing/SHA256HashingUnitTest.java
deleted file mode 100644
index 6bc9ad2cc6..0000000000
--- a/core-java-modules/core-java-security/src/test/java/com/baeldung/hashing/SHA256HashingUnitTest.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.baeldung.hashing;
-
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-
-public class SHA256HashingUnitTest {
-
- private static String originalValue = "abc123";
- private static String hashedValue = "6ca13d52ca70c883e0f0bb101e425a89e8624de51db2d2392593af6a84118090";
-
- @Test
- public void testHashWithJavaMessageDigest() throws Exception {
- final String currentHashedValue = SHA256Hashing.HashWithJavaMessageDigest(originalValue);
- assertEquals(hashedValue, currentHashedValue);
- }
-
- @Test
- public void testHashWithGuava() throws Exception {
- final String currentHashedValue = SHA256Hashing.hashWithGuava(originalValue);
- assertEquals(hashedValue, currentHashedValue);
- }
-
- @Test
- public void testHashWithApacheCommans() throws Exception {
- final String currentHashedValue = SHA256Hashing.HashWithApacheCommons(originalValue);
- assertEquals(hashedValue, currentHashedValue);
- }
-
- @Test
- public void testHashWithBouncyCastle() throws Exception {
- final String currentHashedValue = SHA256Hashing.HashWithBouncyCastle(originalValue);
- assertEquals(hashedValue, currentHashedValue);
- }
-}
\ No newline at end of file
diff --git a/core-java-modules/core-java-security/src/test/java/com/baeldung/hashing/SHA3HashingUnitTest.java b/core-java-modules/core-java-security/src/test/java/com/baeldung/hashing/SHA3HashingUnitTest.java
deleted file mode 100644
index fffab96405..0000000000
--- a/core-java-modules/core-java-security/src/test/java/com/baeldung/hashing/SHA3HashingUnitTest.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.baeldung.hashing;
-
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-
-public class SHA3HashingUnitTest {
-
- private static String originalValue = "abc123";
- private static String hashedValue = "f58fa3df820114f56e1544354379820cff464c9c41cb3ca0ad0b0843c9bb67ee";
-
- /* works with JDK9+ only */
- //@Test
- public void testHashWithJavaMessageDigestJDK9() throws Exception {
- final String currentHashedValue = SHA3Hashing.hashWithJavaMessageDigestJDK9(originalValue);
- assertEquals(hashedValue, currentHashedValue);
- }
-
- @Test
- public void testHashWithJavaMessageDigest() throws Exception {
- final String currentHashedValue = SHA3Hashing.hashWithJavaMessageDigest(originalValue);
- assertEquals(hashedValue, currentHashedValue);
- }
-
- /* works with JDK9+ only */
- //@Test
- public void testHashWithApacheCommonsJDK9() {
- final String currentHashedValue = SHA3Hashing.hashWithApacheCommonsJDK9(originalValue);
- assertEquals(hashedValue, currentHashedValue);
- }
-
- @Test
- public void testHashWithBouncyCastle() {
- final String currentHashedValue = SHA3Hashing.hashWithBouncyCastle(originalValue);
- assertEquals(hashedValue, currentHashedValue);
- }
-
-}
diff --git a/core-java-modules/core-java-security/src/test/java/com/baeldung/java/md5/JavaMD5UnitTest.java b/core-java-modules/core-java-security/src/test/java/com/baeldung/java/md5/JavaMD5UnitTest.java
deleted file mode 100644
index 67d6918c09..0000000000
--- a/core-java-modules/core-java-security/src/test/java/com/baeldung/java/md5/JavaMD5UnitTest.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package com.baeldung.java.md5;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-import java.io.File;
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Paths;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-
-import javax.xml.bind.DatatypeConverter;
-
-import org.apache.commons.codec.digest.DigestUtils;
-import org.junit.Test;
-
-import com.google.common.hash.HashCode;
-import com.google.common.hash.Hashing;
-
-public class JavaMD5UnitTest {
-
- String filename = "src/test/resources/test_md5.txt";
- String checksum = "5EB63BBBE01EEED093CB22BB8F5ACDC3";
-
- String hash = "35454B055CC325EA1AF2126E27707052";
- String password = "ILoveJava";
-
- @Test
- public void givenPassword_whenHashing_thenVerifying() throws NoSuchAlgorithmException {
- String hash = "35454B055CC325EA1AF2126E27707052";
- String password = "ILoveJava";
-
- MessageDigest md = MessageDigest.getInstance("MD5");
- md.update(password.getBytes());
- byte[] digest = md.digest();
- String myHash = DatatypeConverter.printHexBinary(digest).toUpperCase();
-
- assertThat(myHash.equals(hash)).isTrue();
- }
-
- @Test
- public void givenFile_generatingChecksum_thenVerifying() throws NoSuchAlgorithmException, IOException {
- String filename = "src/test/resources/test_md5.txt";
- String checksum = "5EB63BBBE01EEED093CB22BB8F5ACDC3";
-
- MessageDigest md = MessageDigest.getInstance("MD5");
- md.update(Files.readAllBytes(Paths.get(filename)));
- byte[] digest = md.digest();
- String myChecksum = DatatypeConverter.printHexBinary(digest).toUpperCase();
-
- assertThat(myChecksum.equals(checksum)).isTrue();
- }
-
- @Test
- public void givenPassword_whenHashingUsingCommons_thenVerifying() {
- String hash = "35454B055CC325EA1AF2126E27707052";
- String password = "ILoveJava";
-
- String md5Hex = DigestUtils.md5Hex(password).toUpperCase();
-
- assertThat(md5Hex.equals(hash)).isTrue();
- }
-
- @Test
- public void givenFile_whenChecksumUsingGuava_thenVerifying() throws IOException {
- String filename = "src/test/resources/test_md5.txt";
- String checksum = "5EB63BBBE01EEED093CB22BB8F5ACDC3";
-
- HashCode hash = com.google.common.io.Files.hash(new File(filename), Hashing.md5());
- String myChecksum = hash.toString().toUpperCase();
-
- assertThat(myChecksum.equals(checksum)).isTrue();
- }
-
-}
diff --git a/core-java-modules/core-java-security/src/test/java/com/baeldung/passwordhashing/PBKDF2HasherUnitTest.java b/core-java-modules/core-java-security/src/test/java/com/baeldung/passwordhashing/PBKDF2HasherUnitTest.java
deleted file mode 100644
index 8e90725c77..0000000000
--- a/core-java-modules/core-java-security/src/test/java/com/baeldung/passwordhashing/PBKDF2HasherUnitTest.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package com.baeldung.passwordhashing;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import static org.junit.Assert.*;
-
-
-public class PBKDF2HasherUnitTest {
-
- private PBKDF2Hasher mPBKDF2Hasher;
-
- @Before
- public void setUp() throws Exception {
- mPBKDF2Hasher = new PBKDF2Hasher();
- }
-
- @Test
- public void givenCorrectMessageAndHash_whenAuthenticated_checkAuthenticationSucceeds() throws Exception {
- String message1 = "password123";
-
- String hash1 = mPBKDF2Hasher.hash(message1.toCharArray());
-
- assertTrue(mPBKDF2Hasher.checkPassword(message1.toCharArray(), hash1));
-
- }
-
- @Test
- public void givenWrongMessage_whenAuthenticated_checkAuthenticationFails() throws Exception {
- String message1 = "password123";
-
- String hash1 = mPBKDF2Hasher.hash(message1.toCharArray());
-
- String wrongPasswordAttempt = "IamWrong";
-
- assertFalse(mPBKDF2Hasher.checkPassword(wrongPasswordAttempt.toCharArray(), hash1));
-
- }
-
-
-}
\ No newline at end of file
diff --git a/core-java-modules/core-java-security/src/test/java/com/baeldung/passwordhashing/SHA512HasherUnitTest.java b/core-java-modules/core-java-security/src/test/java/com/baeldung/passwordhashing/SHA512HasherUnitTest.java
deleted file mode 100644
index 3acfb0ba9d..0000000000
--- a/core-java-modules/core-java-security/src/test/java/com/baeldung/passwordhashing/SHA512HasherUnitTest.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package com.baeldung.passwordhashing;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import java.security.SecureRandom;
-
-import static org.junit.Assert.*;
-
-/**
- * Created by PhysicsSam on 06-Sep-18.
- */
-public class SHA512HasherUnitTest {
-
- private SHA512Hasher hasher;
- private SecureRandom secureRandom;
-
- @Before
- public void setUp() throws Exception {
- hasher = new SHA512Hasher();
- secureRandom = new SecureRandom();
- }
-
- @Test
- public void givenSamePasswordAndSalt_whenHashed_checkResultingHashesAreEqual() throws Exception {
-
- byte[] salt = new byte[16];
- secureRandom.nextBytes(salt);
-
- String hash1 = hasher.hash("password", salt);
- String hash2 = hasher.hash("password", salt);
-
- assertEquals(hash1, hash2);
-
- }
-
- @Test
- public void givenSamePasswordAndDifferentSalt_whenHashed_checkResultingHashesNotEqual() throws Exception {
-
- byte[] salt = new byte[16];
- secureRandom.nextBytes(salt);
- String hash1 = hasher.hash("password", salt);
- //generate a second salt
- byte[] secondSalt = new byte[16];
- String hash2 = hasher.hash("password", secondSalt);
-
- assertNotEquals(hash1, hash2);
-
- }
-
- @Test
- public void givenPredefinedHash_whenCorrectAttemptGiven_checkAuthenticationSucceeds() throws Exception {
- byte[] salt = new byte[16];
- secureRandom.nextBytes(salt);
-
- String originalHash = hasher.hash("password123", salt);
-
- assertTrue(hasher.checkPassword(originalHash, "password123", salt));
- }
-
- @Test
- public void givenPredefinedHash_whenIncorrectAttemptGiven_checkAuthenticationFails() throws Exception {
- byte[] salt = new byte[16];
- secureRandom.nextBytes(salt);
-
- String originalHash = hasher.hash("password123", salt);
-
- assertFalse(hasher.checkPassword(originalHash, "password124", salt));
- }
-}
\ No newline at end of file
diff --git a/core-java-modules/core-java-security/src/test/resources/test_md5.txt b/core-java-modules/core-java-security/src/test/resources/test_md5.txt
deleted file mode 100644
index 95d09f2b10..0000000000
--- a/core-java-modules/core-java-security/src/test/resources/test_md5.txt
+++ /dev/null
@@ -1 +0,0 @@
-hello world
\ No newline at end of file
From e2b6b4bc924f860cd2ab7d77ed17ad8e2d969b15 Mon Sep 17 00:00:00 2001
From: sampadawagde
Date: Sat, 28 Mar 2020 16:48:43 +0530
Subject: [PATCH 039/187] JAVA-623: Moved 3 articles to core-java-security-2
---
.../core-java-security-2/README.md | 8 +
.../core-java-security-2/pom.xml | 30 ++++
.../baeldung/hashing/DigestAlgorithms.java | 9 ++
.../baeldung/hashing/Keccak256Hashing.java | 30 ++++
.../com/baeldung/hashing/SHA256Hashing.java | 39 +++++
.../com/baeldung/hashing/SHA3Hashing.java | 45 ++++++
.../com/baeldung/hashing/SHACommonUtils.java | 16 ++
.../passwordhashing/PBKDF2Hasher.java | 149 ++++++++++++++++++
.../passwordhashing/SHA512Hasher.java | 35 ++++
.../passwordhashing/SimplePBKDF2Hasher.java | 18 +++
.../hashing/Keccak256HashingUnitTest.java | 22 +++
.../hashing/SHA256HashingUnitTest.java | 35 ++++
.../baeldung/hashing/SHA3HashingUnitTest.java | 38 +++++
.../baeldung/java/md5/JavaMD5UnitTest.java | 75 +++++++++
.../passwordhashing/PBKDF2HasherUnitTest.java | 41 +++++
.../passwordhashing/SHA512HasherUnitTest.java | 70 ++++++++
.../src/test/resources/test_md5.txt | 1 +
17 files changed, 661 insertions(+)
create mode 100644 core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/DigestAlgorithms.java
create mode 100644 core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/Keccak256Hashing.java
create mode 100644 core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/SHA256Hashing.java
create mode 100644 core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/SHA3Hashing.java
create mode 100644 core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/SHACommonUtils.java
create mode 100644 core-java-modules/core-java-security-2/src/main/java/com/baeldung/passwordhashing/PBKDF2Hasher.java
create mode 100644 core-java-modules/core-java-security-2/src/main/java/com/baeldung/passwordhashing/SHA512Hasher.java
create mode 100644 core-java-modules/core-java-security-2/src/main/java/com/baeldung/passwordhashing/SimplePBKDF2Hasher.java
create mode 100644 core-java-modules/core-java-security-2/src/test/java/com/baeldung/hashing/Keccak256HashingUnitTest.java
create mode 100644 core-java-modules/core-java-security-2/src/test/java/com/baeldung/hashing/SHA256HashingUnitTest.java
create mode 100644 core-java-modules/core-java-security-2/src/test/java/com/baeldung/hashing/SHA3HashingUnitTest.java
create mode 100644 core-java-modules/core-java-security-2/src/test/java/com/baeldung/java/md5/JavaMD5UnitTest.java
create mode 100644 core-java-modules/core-java-security-2/src/test/java/com/baeldung/passwordhashing/PBKDF2HasherUnitTest.java
create mode 100644 core-java-modules/core-java-security-2/src/test/java/com/baeldung/passwordhashing/SHA512HasherUnitTest.java
create mode 100644 core-java-modules/core-java-security-2/src/test/resources/test_md5.txt
diff --git a/core-java-modules/core-java-security-2/README.md b/core-java-modules/core-java-security-2/README.md
index c250e24078..2eb21fb77e 100644
--- a/core-java-modules/core-java-security-2/README.md
+++ b/core-java-modules/core-java-security-2/README.md
@@ -1,3 +1,11 @@
+## Core Java Security
+
+This module contains articles about core Java Security
+
### Relevant Articles:
- [Guide To The Java Authentication And Authorization Service (JAAS)](https://www.baeldung.com/java-authentication-authorization-service)
+- [MD5 Hashing in Java](http://www.baeldung.com/java-md5)
+- [Hashing a Password in Java](https://www.baeldung.com/java-password-hashing)
+- [SHA-256 and SHA3-256 Hashing in Java](https://www.baeldung.com/sha-256-hashing-java)
+- More articles: [[<-- prev]](/core-java-modules/core-java-security)
diff --git a/core-java-modules/core-java-security-2/pom.xml b/core-java-modules/core-java-security-2/pom.xml
index 23f0c5aab9..9315ab4af2 100644
--- a/core-java-modules/core-java-security-2/pom.xml
+++ b/core-java-modules/core-java-security-2/pom.xml
@@ -16,4 +16,34 @@
../../parent-java
+
+
+ commons-codec
+ commons-codec
+ ${commons-codec.version}
+
+
+
+ org.bouncycastle
+ bcprov-jdk15on
+ ${bouncycastle.version}
+
+
+
+
+ org.assertj
+ assertj-core
+ ${assertj-core.version}
+ test
+
+
+
+
+
+ 1.60
+ 1.11
+
+
+ 3.10.0
+
diff --git a/core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/DigestAlgorithms.java b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/DigestAlgorithms.java
new file mode 100644
index 0000000000..94dd22ff4b
--- /dev/null
+++ b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/DigestAlgorithms.java
@@ -0,0 +1,9 @@
+package com.baeldung.hashing;
+
+public class DigestAlgorithms {
+
+ public static final String SHA3_256 = "SHA3-256";
+ public static final String SHA_256 = "SHA-256";
+ public static final String KECCAK_256 = "Keccak-256";
+
+}
diff --git a/core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/Keccak256Hashing.java b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/Keccak256Hashing.java
new file mode 100644
index 0000000000..19fc4cf059
--- /dev/null
+++ b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/Keccak256Hashing.java
@@ -0,0 +1,30 @@
+package com.baeldung.hashing;
+
+import org.bouncycastle.jcajce.provider.digest.Keccak;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.util.encoders.Hex;
+
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.Security;
+
+import static com.baeldung.hashing.DigestAlgorithms.KECCAK_256;
+import static com.baeldung.hashing.SHACommonUtils.bytesToHex;
+
+public class Keccak256Hashing {
+
+ public static String hashWithJavaMessageDigest(final String originalString) throws NoSuchAlgorithmException {
+ Security.addProvider(new BouncyCastleProvider());
+ final MessageDigest digest = MessageDigest.getInstance(KECCAK_256);
+ final byte[] encodedhash = digest.digest(originalString.getBytes(StandardCharsets.UTF_8));
+ return bytesToHex(encodedhash);
+ }
+
+ public static String hashWithBouncyCastle(final String originalString) {
+ Keccak.Digest256 digest256 = new Keccak.Digest256();
+ byte[] hashbytes = digest256.digest(originalString.getBytes(StandardCharsets.UTF_8));
+ return new String(Hex.encode(hashbytes));
+ }
+
+}
diff --git a/core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/SHA256Hashing.java b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/SHA256Hashing.java
new file mode 100644
index 0000000000..ec008cebab
--- /dev/null
+++ b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/SHA256Hashing.java
@@ -0,0 +1,39 @@
+package com.baeldung.hashing;
+
+import com.google.common.hash.Hashing;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.bouncycastle.util.encoders.Hex;
+
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+import static com.baeldung.hashing.DigestAlgorithms.SHA_256;
+import static com.baeldung.hashing.SHACommonUtils.bytesToHex;
+
+public class SHA256Hashing {
+
+ public static String HashWithJavaMessageDigest(final String originalString) throws NoSuchAlgorithmException {
+ final MessageDigest digest = MessageDigest.getInstance(SHA_256);
+ final byte[] encodedhash = digest.digest(originalString.getBytes(StandardCharsets.UTF_8));
+ return bytesToHex(encodedhash);
+ }
+
+ public static String hashWithGuava(final String originalString) {
+ final String sha256hex = Hashing.sha256().hashString(originalString, StandardCharsets.UTF_8).toString();
+ return sha256hex;
+ }
+
+ public static String HashWithApacheCommons(final String originalString) {
+ final String sha256hex = DigestUtils.sha256Hex(originalString);
+ return sha256hex;
+ }
+
+ public static String HashWithBouncyCastle(final String originalString) throws NoSuchAlgorithmException {
+ final MessageDigest digest = MessageDigest.getInstance(SHA_256);
+ final byte[] hash = digest.digest(originalString.getBytes(StandardCharsets.UTF_8));
+ final String sha256hex = new String(Hex.encode(hash));
+ return sha256hex;
+ }
+
+}
diff --git a/core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/SHA3Hashing.java b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/SHA3Hashing.java
new file mode 100644
index 0000000000..eb363205b1
--- /dev/null
+++ b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/SHA3Hashing.java
@@ -0,0 +1,45 @@
+package com.baeldung.hashing;
+
+import com.google.common.hash.Hashing;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.bouncycastle.crypto.digests.SHA3Digest;
+import org.bouncycastle.jcajce.provider.digest.SHA3;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.util.encoders.Hex;
+
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.Security;
+
+import static com.baeldung.hashing.DigestAlgorithms.SHA3_256;
+import static com.baeldung.hashing.SHACommonUtils.bytesToHex;
+
+public class SHA3Hashing {
+
+ /* works with JDK9+ only */
+ public static String hashWithJavaMessageDigestJDK9(final String originalString) throws NoSuchAlgorithmException {
+ final MessageDigest digest = MessageDigest.getInstance(SHA3_256);
+ final byte[] hashbytes = digest.digest(originalString.getBytes(StandardCharsets.UTF_8));
+ return bytesToHex(hashbytes);
+ }
+
+ public static String hashWithJavaMessageDigest(final String originalString) throws NoSuchAlgorithmException {
+ Security.addProvider(new BouncyCastleProvider());
+ final MessageDigest digest = MessageDigest.getInstance(SHA3_256);
+ final byte[] hashbytes = digest.digest(originalString.getBytes(StandardCharsets.UTF_8));
+ return bytesToHex(hashbytes);
+ }
+
+ /* works with JDK9+ only */
+ public static String hashWithApacheCommonsJDK9(final String originalString) {
+ return new DigestUtils(SHA3_256).digestAsHex(originalString);
+ }
+
+ public static String hashWithBouncyCastle(final String originalString) {
+ SHA3.Digest256 digest256 = new SHA3.Digest256();
+ byte[] hashbytes = digest256.digest(originalString.getBytes(StandardCharsets.UTF_8));
+ return new String(Hex.encode(hashbytes));
+ }
+
+}
diff --git a/core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/SHACommonUtils.java b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/SHACommonUtils.java
new file mode 100644
index 0000000000..0f28408083
--- /dev/null
+++ b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/SHACommonUtils.java
@@ -0,0 +1,16 @@
+package com.baeldung.hashing;
+
+class SHACommonUtils {
+
+ public static String bytesToHex(byte[] hash) {
+ StringBuffer hexString = new StringBuffer();
+ for (byte h : hash) {
+ String hex = Integer.toHexString(0xff & h);
+ if (hex.length() == 1)
+ hexString.append('0');
+ hexString.append(hex);
+ }
+ return hexString.toString();
+ }
+
+}
diff --git a/core-java-modules/core-java-security-2/src/main/java/com/baeldung/passwordhashing/PBKDF2Hasher.java b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/passwordhashing/PBKDF2Hasher.java
new file mode 100644
index 0000000000..e2259e4249
--- /dev/null
+++ b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/passwordhashing/PBKDF2Hasher.java
@@ -0,0 +1,149 @@
+package com.baeldung.passwordhashing;
+
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.KeySpec;
+import java.util.Arrays;
+import java.util.Base64;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.PBEKeySpec;
+
+/**
+ * Hash passwords for storage, and test passwords against password tokens.
+ *
+ * Instances of this class can be used concurrently by multiple threads.
+ *
+ * @author erickson
+ * @see StackOverflow
+ */
+public final class PBKDF2Hasher
+{
+
+ /**
+ * Each token produced by this class uses this identifier as a prefix.
+ */
+ public static final String ID = "$31$";
+
+ /**
+ * The minimum recommended cost, used by default
+ */
+ public static final int DEFAULT_COST = 16;
+
+ private static final String ALGORITHM = "PBKDF2WithHmacSHA1";
+
+ private static final int SIZE = 128;
+
+ private static final Pattern layout = Pattern.compile("\\$31\\$(\\d\\d?)\\$(.{43})");
+
+ private final SecureRandom random;
+
+ private final int cost;
+
+ public PBKDF2Hasher()
+ {
+ this(DEFAULT_COST);
+ }
+
+ /**
+ * Create a password manager with a specified cost
+ *
+ * @param cost the exponential computational cost of hashing a password, 0 to 30
+ */
+ public PBKDF2Hasher(int cost)
+ {
+ iterations(cost); /* Validate cost */
+ this.cost = cost;
+ this.random = new SecureRandom();
+ }
+
+ private static int iterations(int cost)
+ {
+ if ((cost < 0) || (cost > 30))
+ throw new IllegalArgumentException("cost: " + cost);
+ return 1 << cost;
+ }
+
+ /**
+ * Hash a password for storage.
+ *
+ * @return a secure authentication token to be stored for later authentication
+ */
+ public String hash(char[] password)
+ {
+ byte[] salt = new byte[SIZE / 8];
+ random.nextBytes(salt);
+ byte[] dk = pbkdf2(password, salt, 1 << cost);
+ byte[] hash = new byte[salt.length + dk.length];
+ System.arraycopy(salt, 0, hash, 0, salt.length);
+ System.arraycopy(dk, 0, hash, salt.length, dk.length);
+ Base64.Encoder enc = Base64.getUrlEncoder().withoutPadding();
+ return ID + cost + '$' + enc.encodeToString(hash);
+ }
+
+ /**
+ * Authenticate with a password and a stored password token.
+ *
+ * @return true if the password and token match
+ */
+ public boolean checkPassword(char[] password, String token)
+ {
+ Matcher m = layout.matcher(token);
+ if (!m.matches())
+ throw new IllegalArgumentException("Invalid token format");
+ int iterations = iterations(Integer.parseInt(m.group(1)));
+ byte[] hash = Base64.getUrlDecoder().decode(m.group(2));
+ byte[] salt = Arrays.copyOfRange(hash, 0, SIZE / 8);
+ byte[] check = pbkdf2(password, salt, iterations);
+ int zero = 0;
+ for (int idx = 0; idx < check.length; ++idx)
+ zero |= hash[salt.length + idx] ^ check[idx];
+ return zero == 0;
+ }
+
+ private static byte[] pbkdf2(char[] password, byte[] salt, int iterations)
+ {
+ KeySpec spec = new PBEKeySpec(password, salt, iterations, SIZE);
+ try {
+ SecretKeyFactory f = SecretKeyFactory.getInstance(ALGORITHM);
+ return f.generateSecret(spec).getEncoded();
+ }
+ catch (NoSuchAlgorithmException ex) {
+ throw new IllegalStateException("Missing algorithm: " + ALGORITHM, ex);
+ }
+ catch (InvalidKeySpecException ex) {
+ throw new IllegalStateException("Invalid SecretKeyFactory", ex);
+ }
+ }
+
+ /**
+ * Hash a password in an immutable {@code String}.
+ *
+ * Passwords should be stored in a {@code char[]} so that it can be filled
+ * with zeros after use instead of lingering on the heap and elsewhere.
+ *
+ * @deprecated Use {@link #hash(char[])} instead
+ */
+ @Deprecated
+ public String hash(String password)
+ {
+ return hash(password.toCharArray());
+ }
+
+ /**
+ * Authenticate with a password in an immutable {@code String} and a stored
+ * password token.
+ *
+ * @deprecated Use {@link #checkPassword(char[],String)} instead.
+ * @see #hash(String)
+ */
+ @Deprecated
+ public boolean checkPassword(String password, String token)
+ {
+ return checkPassword(password.toCharArray(), token);
+ }
+
+}
diff --git a/core-java-modules/core-java-security-2/src/main/java/com/baeldung/passwordhashing/SHA512Hasher.java b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/passwordhashing/SHA512Hasher.java
new file mode 100644
index 0000000000..4f5337f963
--- /dev/null
+++ b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/passwordhashing/SHA512Hasher.java
@@ -0,0 +1,35 @@
+package com.baeldung.passwordhashing;
+
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+
+/** A really simple SHA_512 Encryption example.
+ *
+ */
+public class SHA512Hasher {
+
+ public String hash(String passwordToHash, byte[] salt){
+ String generatedPassword = null;
+ try {
+ MessageDigest md = MessageDigest.getInstance("SHA-512");
+ md.update(salt);
+ byte[] bytes = md.digest(passwordToHash.getBytes(StandardCharsets.UTF_8));
+ StringBuilder sb = new StringBuilder();
+ for(int i=0; i< bytes.length ;i++){
+ sb.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1));
+ }
+ generatedPassword = sb.toString();
+ }
+ catch (NoSuchAlgorithmException e){
+ e.printStackTrace();
+ }
+ return generatedPassword;
+ }
+
+ public boolean checkPassword(String hash, String attempt, byte[] salt){
+ String generatedHash = hash(attempt, salt);
+ return hash.equals(generatedHash);
+ }
+}
diff --git a/core-java-modules/core-java-security-2/src/main/java/com/baeldung/passwordhashing/SimplePBKDF2Hasher.java b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/passwordhashing/SimplePBKDF2Hasher.java
new file mode 100644
index 0000000000..36c9b65070
--- /dev/null
+++ b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/passwordhashing/SimplePBKDF2Hasher.java
@@ -0,0 +1,18 @@
+package com.baeldung.passwordhashing;
+
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.PBEKeySpec;
+import java.security.spec.KeySpec;
+
+/** A really simple SimplePBKDF2 Encryption example.
+ *
+ */
+public class SimplePBKDF2Hasher {
+
+ public static String hashSimple(String password, byte[] salt) throws Exception{
+ KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 65536, 128);
+ SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
+ byte[] hash = f.generateSecret(spec).getEncoded();
+ return String.valueOf(hash);
+ }
+}
diff --git a/core-java-modules/core-java-security-2/src/test/java/com/baeldung/hashing/Keccak256HashingUnitTest.java b/core-java-modules/core-java-security-2/src/test/java/com/baeldung/hashing/Keccak256HashingUnitTest.java
new file mode 100644
index 0000000000..9ed35c8834
--- /dev/null
+++ b/core-java-modules/core-java-security-2/src/test/java/com/baeldung/hashing/Keccak256HashingUnitTest.java
@@ -0,0 +1,22 @@
+package com.baeldung.hashing;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class Keccak256HashingUnitTest {
+
+ private static String originalValue = "abc123";
+ private static String hashedValue = "719accc61a9cc126830e5906f9d672d06eab6f8597287095a2c55a8b775e7016";
+
+ @Test public void testHashWithJavaMessageDigest() throws Exception {
+ final String currentHashedValue = Keccak256Hashing.hashWithJavaMessageDigest(originalValue);
+ assertEquals(hashedValue, currentHashedValue);
+ }
+
+ @Test public void testHashWithBouncyCastle() {
+ final String currentHashedValue = Keccak256Hashing.hashWithBouncyCastle(originalValue);
+ assertEquals(hashedValue, currentHashedValue);
+ }
+
+}
diff --git a/core-java-modules/core-java-security-2/src/test/java/com/baeldung/hashing/SHA256HashingUnitTest.java b/core-java-modules/core-java-security-2/src/test/java/com/baeldung/hashing/SHA256HashingUnitTest.java
new file mode 100644
index 0000000000..6bc9ad2cc6
--- /dev/null
+++ b/core-java-modules/core-java-security-2/src/test/java/com/baeldung/hashing/SHA256HashingUnitTest.java
@@ -0,0 +1,35 @@
+package com.baeldung.hashing;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class SHA256HashingUnitTest {
+
+ private static String originalValue = "abc123";
+ private static String hashedValue = "6ca13d52ca70c883e0f0bb101e425a89e8624de51db2d2392593af6a84118090";
+
+ @Test
+ public void testHashWithJavaMessageDigest() throws Exception {
+ final String currentHashedValue = SHA256Hashing.HashWithJavaMessageDigest(originalValue);
+ assertEquals(hashedValue, currentHashedValue);
+ }
+
+ @Test
+ public void testHashWithGuava() throws Exception {
+ final String currentHashedValue = SHA256Hashing.hashWithGuava(originalValue);
+ assertEquals(hashedValue, currentHashedValue);
+ }
+
+ @Test
+ public void testHashWithApacheCommans() throws Exception {
+ final String currentHashedValue = SHA256Hashing.HashWithApacheCommons(originalValue);
+ assertEquals(hashedValue, currentHashedValue);
+ }
+
+ @Test
+ public void testHashWithBouncyCastle() throws Exception {
+ final String currentHashedValue = SHA256Hashing.HashWithBouncyCastle(originalValue);
+ assertEquals(hashedValue, currentHashedValue);
+ }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-security-2/src/test/java/com/baeldung/hashing/SHA3HashingUnitTest.java b/core-java-modules/core-java-security-2/src/test/java/com/baeldung/hashing/SHA3HashingUnitTest.java
new file mode 100644
index 0000000000..fffab96405
--- /dev/null
+++ b/core-java-modules/core-java-security-2/src/test/java/com/baeldung/hashing/SHA3HashingUnitTest.java
@@ -0,0 +1,38 @@
+package com.baeldung.hashing;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class SHA3HashingUnitTest {
+
+ private static String originalValue = "abc123";
+ private static String hashedValue = "f58fa3df820114f56e1544354379820cff464c9c41cb3ca0ad0b0843c9bb67ee";
+
+ /* works with JDK9+ only */
+ //@Test
+ public void testHashWithJavaMessageDigestJDK9() throws Exception {
+ final String currentHashedValue = SHA3Hashing.hashWithJavaMessageDigestJDK9(originalValue);
+ assertEquals(hashedValue, currentHashedValue);
+ }
+
+ @Test
+ public void testHashWithJavaMessageDigest() throws Exception {
+ final String currentHashedValue = SHA3Hashing.hashWithJavaMessageDigest(originalValue);
+ assertEquals(hashedValue, currentHashedValue);
+ }
+
+ /* works with JDK9+ only */
+ //@Test
+ public void testHashWithApacheCommonsJDK9() {
+ final String currentHashedValue = SHA3Hashing.hashWithApacheCommonsJDK9(originalValue);
+ assertEquals(hashedValue, currentHashedValue);
+ }
+
+ @Test
+ public void testHashWithBouncyCastle() {
+ final String currentHashedValue = SHA3Hashing.hashWithBouncyCastle(originalValue);
+ assertEquals(hashedValue, currentHashedValue);
+ }
+
+}
diff --git a/core-java-modules/core-java-security-2/src/test/java/com/baeldung/java/md5/JavaMD5UnitTest.java b/core-java-modules/core-java-security-2/src/test/java/com/baeldung/java/md5/JavaMD5UnitTest.java
new file mode 100644
index 0000000000..67d6918c09
--- /dev/null
+++ b/core-java-modules/core-java-security-2/src/test/java/com/baeldung/java/md5/JavaMD5UnitTest.java
@@ -0,0 +1,75 @@
+package com.baeldung.java.md5;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+import javax.xml.bind.DatatypeConverter;
+
+import org.apache.commons.codec.digest.DigestUtils;
+import org.junit.Test;
+
+import com.google.common.hash.HashCode;
+import com.google.common.hash.Hashing;
+
+public class JavaMD5UnitTest {
+
+ String filename = "src/test/resources/test_md5.txt";
+ String checksum = "5EB63BBBE01EEED093CB22BB8F5ACDC3";
+
+ String hash = "35454B055CC325EA1AF2126E27707052";
+ String password = "ILoveJava";
+
+ @Test
+ public void givenPassword_whenHashing_thenVerifying() throws NoSuchAlgorithmException {
+ String hash = "35454B055CC325EA1AF2126E27707052";
+ String password = "ILoveJava";
+
+ MessageDigest md = MessageDigest.getInstance("MD5");
+ md.update(password.getBytes());
+ byte[] digest = md.digest();
+ String myHash = DatatypeConverter.printHexBinary(digest).toUpperCase();
+
+ assertThat(myHash.equals(hash)).isTrue();
+ }
+
+ @Test
+ public void givenFile_generatingChecksum_thenVerifying() throws NoSuchAlgorithmException, IOException {
+ String filename = "src/test/resources/test_md5.txt";
+ String checksum = "5EB63BBBE01EEED093CB22BB8F5ACDC3";
+
+ MessageDigest md = MessageDigest.getInstance("MD5");
+ md.update(Files.readAllBytes(Paths.get(filename)));
+ byte[] digest = md.digest();
+ String myChecksum = DatatypeConverter.printHexBinary(digest).toUpperCase();
+
+ assertThat(myChecksum.equals(checksum)).isTrue();
+ }
+
+ @Test
+ public void givenPassword_whenHashingUsingCommons_thenVerifying() {
+ String hash = "35454B055CC325EA1AF2126E27707052";
+ String password = "ILoveJava";
+
+ String md5Hex = DigestUtils.md5Hex(password).toUpperCase();
+
+ assertThat(md5Hex.equals(hash)).isTrue();
+ }
+
+ @Test
+ public void givenFile_whenChecksumUsingGuava_thenVerifying() throws IOException {
+ String filename = "src/test/resources/test_md5.txt";
+ String checksum = "5EB63BBBE01EEED093CB22BB8F5ACDC3";
+
+ HashCode hash = com.google.common.io.Files.hash(new File(filename), Hashing.md5());
+ String myChecksum = hash.toString().toUpperCase();
+
+ assertThat(myChecksum.equals(checksum)).isTrue();
+ }
+
+}
diff --git a/core-java-modules/core-java-security-2/src/test/java/com/baeldung/passwordhashing/PBKDF2HasherUnitTest.java b/core-java-modules/core-java-security-2/src/test/java/com/baeldung/passwordhashing/PBKDF2HasherUnitTest.java
new file mode 100644
index 0000000000..8e90725c77
--- /dev/null
+++ b/core-java-modules/core-java-security-2/src/test/java/com/baeldung/passwordhashing/PBKDF2HasherUnitTest.java
@@ -0,0 +1,41 @@
+package com.baeldung.passwordhashing;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+
+public class PBKDF2HasherUnitTest {
+
+ private PBKDF2Hasher mPBKDF2Hasher;
+
+ @Before
+ public void setUp() throws Exception {
+ mPBKDF2Hasher = new PBKDF2Hasher();
+ }
+
+ @Test
+ public void givenCorrectMessageAndHash_whenAuthenticated_checkAuthenticationSucceeds() throws Exception {
+ String message1 = "password123";
+
+ String hash1 = mPBKDF2Hasher.hash(message1.toCharArray());
+
+ assertTrue(mPBKDF2Hasher.checkPassword(message1.toCharArray(), hash1));
+
+ }
+
+ @Test
+ public void givenWrongMessage_whenAuthenticated_checkAuthenticationFails() throws Exception {
+ String message1 = "password123";
+
+ String hash1 = mPBKDF2Hasher.hash(message1.toCharArray());
+
+ String wrongPasswordAttempt = "IamWrong";
+
+ assertFalse(mPBKDF2Hasher.checkPassword(wrongPasswordAttempt.toCharArray(), hash1));
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-security-2/src/test/java/com/baeldung/passwordhashing/SHA512HasherUnitTest.java b/core-java-modules/core-java-security-2/src/test/java/com/baeldung/passwordhashing/SHA512HasherUnitTest.java
new file mode 100644
index 0000000000..3acfb0ba9d
--- /dev/null
+++ b/core-java-modules/core-java-security-2/src/test/java/com/baeldung/passwordhashing/SHA512HasherUnitTest.java
@@ -0,0 +1,70 @@
+package com.baeldung.passwordhashing;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.security.SecureRandom;
+
+import static org.junit.Assert.*;
+
+/**
+ * Created by PhysicsSam on 06-Sep-18.
+ */
+public class SHA512HasherUnitTest {
+
+ private SHA512Hasher hasher;
+ private SecureRandom secureRandom;
+
+ @Before
+ public void setUp() throws Exception {
+ hasher = new SHA512Hasher();
+ secureRandom = new SecureRandom();
+ }
+
+ @Test
+ public void givenSamePasswordAndSalt_whenHashed_checkResultingHashesAreEqual() throws Exception {
+
+ byte[] salt = new byte[16];
+ secureRandom.nextBytes(salt);
+
+ String hash1 = hasher.hash("password", salt);
+ String hash2 = hasher.hash("password", salt);
+
+ assertEquals(hash1, hash2);
+
+ }
+
+ @Test
+ public void givenSamePasswordAndDifferentSalt_whenHashed_checkResultingHashesNotEqual() throws Exception {
+
+ byte[] salt = new byte[16];
+ secureRandom.nextBytes(salt);
+ String hash1 = hasher.hash("password", salt);
+ //generate a second salt
+ byte[] secondSalt = new byte[16];
+ String hash2 = hasher.hash("password", secondSalt);
+
+ assertNotEquals(hash1, hash2);
+
+ }
+
+ @Test
+ public void givenPredefinedHash_whenCorrectAttemptGiven_checkAuthenticationSucceeds() throws Exception {
+ byte[] salt = new byte[16];
+ secureRandom.nextBytes(salt);
+
+ String originalHash = hasher.hash("password123", salt);
+
+ assertTrue(hasher.checkPassword(originalHash, "password123", salt));
+ }
+
+ @Test
+ public void givenPredefinedHash_whenIncorrectAttemptGiven_checkAuthenticationFails() throws Exception {
+ byte[] salt = new byte[16];
+ secureRandom.nextBytes(salt);
+
+ String originalHash = hasher.hash("password123", salt);
+
+ assertFalse(hasher.checkPassword(originalHash, "password124", salt));
+ }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-security-2/src/test/resources/test_md5.txt b/core-java-modules/core-java-security-2/src/test/resources/test_md5.txt
new file mode 100644
index 0000000000..95d09f2b10
--- /dev/null
+++ b/core-java-modules/core-java-security-2/src/test/resources/test_md5.txt
@@ -0,0 +1 @@
+hello world
\ No newline at end of file
From 2ba09756f7fe2efdb8198d4cba4952e1e88a4314 Mon Sep 17 00:00:00 2001
From: Antonio Moreno
Date: Tue, 24 Mar 2020 23:43:49 +0000
Subject: [PATCH 040/187] BAEL-3928 Comparing Long values in Java
---
.../comparelong/CompareLongUnitTest.java | 53 +++++++++++++++++++
1 file changed, 53 insertions(+)
create mode 100644 core-java-modules/core-java-lang-2/src/test/java/com/baeldung/comparelong/CompareLongUnitTest.java
diff --git a/core-java-modules/core-java-lang-2/src/test/java/com/baeldung/comparelong/CompareLongUnitTest.java b/core-java-modules/core-java-lang-2/src/test/java/com/baeldung/comparelong/CompareLongUnitTest.java
new file mode 100644
index 0000000000..ab4ea2b657
--- /dev/null
+++ b/core-java-modules/core-java-lang-2/src/test/java/com/baeldung/comparelong/CompareLongUnitTest.java
@@ -0,0 +1,53 @@
+package com.baeldung.comparelong;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import org.junit.Test;
+
+public class CompareLongUnitTest {
+
+ @Test
+ public void givenLongValuesLessThan128_whenUsingReferenceComparater_thenSuccess() {
+
+ Long l1 = 127L;
+ Long l2 = 127L;
+
+ assertThat(l1 == l2).isTrue();
+ }
+
+ @Test
+ public void givenLongValuesGreaterOrEqualsThan128_whenUsingReferenceComparater_thenFails() {
+
+ Long l1 = 128L;
+ Long l2 = 128L;
+
+ assertThat(l1 == l2).isFalse();
+ }
+
+ @Test
+ public void givenLongValuesGreaterOrEqualsThan128_whenUsingEquals_thenSuccess() {
+
+ Long l1 = 128L;
+ Long l2 = 128L;
+
+ assertThat(l1.equals(l2)).isTrue();
+ }
+
+ @Test
+ public void givenLongValuesGreaterOrEqualsThan128_whenUsingComparisonOperator_andLongValue_thenSuccess() {
+
+ Long l1 = 128L;
+ Long l2 = 128L;
+
+ assertThat(l1.longValue() == l2.longValue()).isTrue();
+ }
+
+ @Test
+ public void givenLongValuesGreaterOrEqualsThan128_whenUsingCasting_thenSuccess() {
+
+ Long l1 = 128L;
+ Long l2 = 128L;
+
+ assertThat((long) l1 == (long) l2).isTrue();
+ }
+
+}
\ No newline at end of file
From c6f71e7ac7bae3587fdabcc49329fec817af38e7 Mon Sep 17 00:00:00 2001
From: Kai Yuan
Date: Thu, 26 Mar 2020 23:00:07 +0100
Subject: [PATCH 041/187] [BAEL-3934]shedlock update
---
.../spring-boot-libraries/pom.xml | 8 +++-
.../main/java/com/baeldung/Application.java | 15 +++++++
.../java/com/baeldung/boot/Application.java | 14 -------
...eduler.java => BaeldungTaskScheduler.java} | 5 +--
.../shedlock/SchedulerConfiguration.java | 14 ++++---
.../src/main/resources/application.yml | 6 +++
.../BaeldungTaskSchedulerIntegrationTest.java | 39 +++++++++++++++++++
7 files changed, 78 insertions(+), 23 deletions(-)
create mode 100644 spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/Application.java
delete mode 100644 spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/boot/Application.java
rename spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/scheduling/shedlock/{TaskScheduler.java => BaeldungTaskScheduler.java} (85%)
create mode 100644 spring-boot-modules/spring-boot-libraries/src/main/resources/application.yml
create mode 100644 spring-boot-modules/spring-boot-libraries/src/test/java/com/baeldung/scheduling/shedlock/BaeldungTaskSchedulerIntegrationTest.java
diff --git a/spring-boot-modules/spring-boot-libraries/pom.xml b/spring-boot-modules/spring-boot-libraries/pom.xml
index e9d955edc0..2b1b1b7d12 100644
--- a/spring-boot-modules/spring-boot-libraries/pom.xml
+++ b/spring-boot-modules/spring-boot-libraries/pom.xml
@@ -52,7 +52,11 @@
shedlock-provider-jdbc-template
${shedlock.version}
-
+
+ com.h2database
+ h2
+ ${h2.version}
+
net.sourceforge.barbecue
@@ -79,6 +83,7 @@
javase
${zxing.version}
+
@@ -185,6 +190,7 @@
2.2.4
2.3.2
0.23.0
+ 1.4.200
2.1.0
1.5-beta1
2.1
diff --git a/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/Application.java b/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/Application.java
new file mode 100644
index 0000000000..15422e1065
--- /dev/null
+++ b/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/Application.java
@@ -0,0 +1,15 @@
+package com.baeldung;
+
+import net.javacrumbs.shedlock.spring.annotation.EnableSchedulerLock;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
+@SpringBootApplication
+@EnableScheduling
+@EnableSchedulerLock(defaultLockAtMostFor = "PT30S")
+public class Application {
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+}
diff --git a/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/boot/Application.java b/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/boot/Application.java
deleted file mode 100644
index cb0d0c1532..0000000000
--- a/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/boot/Application.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.baeldung.boot;
-
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.context.ApplicationContext;
-
-@SpringBootApplication
-public class Application {
- private static ApplicationContext applicationContext;
-
- public static void main(String[] args) {
- applicationContext = SpringApplication.run(Application.class, args);
- }
-}
diff --git a/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/scheduling/shedlock/TaskScheduler.java b/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/scheduling/shedlock/BaeldungTaskScheduler.java
similarity index 85%
rename from spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/scheduling/shedlock/TaskScheduler.java
rename to spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/scheduling/shedlock/BaeldungTaskScheduler.java
index 060afe660e..cd5f63e962 100644
--- a/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/scheduling/shedlock/TaskScheduler.java
+++ b/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/scheduling/shedlock/BaeldungTaskScheduler.java
@@ -5,9 +5,8 @@ import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
-class TaskScheduler {
-
- @Scheduled(cron = "*/15 * * * *")
+class BaeldungTaskScheduler {
+ @Scheduled(cron = "0 0/15 * * * ?")
@SchedulerLock(name = "TaskScheduler_scheduledTask", lockAtLeastForString = "PT5M", lockAtMostForString = "PT14M")
public void scheduledTask() {
System.out.println("Running ShedLock task");
diff --git a/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/scheduling/shedlock/SchedulerConfiguration.java b/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/scheduling/shedlock/SchedulerConfiguration.java
index 74ea39683d..440e1ffc6a 100644
--- a/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/scheduling/shedlock/SchedulerConfiguration.java
+++ b/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/scheduling/shedlock/SchedulerConfiguration.java
@@ -1,12 +1,16 @@
package com.baeldung.scheduling.shedlock;
+import net.javacrumbs.shedlock.core.LockProvider;
+import net.javacrumbs.shedlock.provider.jdbctemplate.JdbcTemplateLockProvider;
+import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
-import net.javacrumbs.shedlock.spring.annotation.EnableSchedulerLock;
-import org.springframework.scheduling.annotation.EnableScheduling;
+
+import javax.sql.DataSource;
@Configuration
-@EnableScheduling
-@EnableSchedulerLock(defaultLockAtMostFor = "PT30S")
public class SchedulerConfiguration {
-
+ @Bean
+ public LockProvider lockProvider(DataSource dataSource) {
+ return new JdbcTemplateLockProvider(dataSource);
+ }
}
\ No newline at end of file
diff --git a/spring-boot-modules/spring-boot-libraries/src/main/resources/application.yml b/spring-boot-modules/spring-boot-libraries/src/main/resources/application.yml
new file mode 100644
index 0000000000..3477520208
--- /dev/null
+++ b/spring-boot-modules/spring-boot-libraries/src/main/resources/application.yml
@@ -0,0 +1,6 @@
+spring:
+ datasource:
+ driverClassName: org.h2.Driver
+ url: jdbc:h2:mem:shedlock_DB;INIT=CREATE SCHEMA IF NOT EXISTS shedlock;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
+ username: sa
+ password:
diff --git a/spring-boot-modules/spring-boot-libraries/src/test/java/com/baeldung/scheduling/shedlock/BaeldungTaskSchedulerIntegrationTest.java b/spring-boot-modules/spring-boot-libraries/src/test/java/com/baeldung/scheduling/shedlock/BaeldungTaskSchedulerIntegrationTest.java
new file mode 100644
index 0000000000..47f42c133f
--- /dev/null
+++ b/spring-boot-modules/spring-boot-libraries/src/test/java/com/baeldung/scheduling/shedlock/BaeldungTaskSchedulerIntegrationTest.java
@@ -0,0 +1,39 @@
+package com.baeldung.scheduling.shedlock;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class BaeldungTaskSchedulerIntegrationTest {
+ @Autowired
+ private BaeldungTaskScheduler taskScheduler;
+
+ @Test
+ public void whenShedLockConfigCorrect_thenSpringCtxtStartsWithoutError() {
+ // save the old out
+ PrintStream old = System.out;
+
+ // Create a stream to hold the output for test
+ ByteArrayOutputStream consoleOutput = new ByteArrayOutputStream();
+ PrintStream ps = new PrintStream(consoleOutput);
+ System.setOut(ps);
+ //test
+ taskScheduler.scheduledTask();
+ System.out.flush();
+ String expected = "Running ShedLock task\n";
+ assertThat(consoleOutput.toString()).isEqualTo(expected);
+
+ //restore the old out
+ System.setOut(old);
+ }
+
+}
\ No newline at end of file
From 1bc12a57df47a42c36097bdbd0cc5247658666b1 Mon Sep 17 00:00:00 2001
From: Ali Dehghani
Date: Sun, 29 Mar 2020 13:16:38 +0430
Subject: [PATCH 042/187] Ignoring a Bad Flaky Test
---
.../hibernate/criteria/HibernateCriteriaIntegrationTest.java | 2 ++
1 file changed, 2 insertions(+)
diff --git a/persistence-modules/spring-hibernate-5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaIntegrationTest.java b/persistence-modules/spring-hibernate-5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaIntegrationTest.java
index 31877255b2..7d95e0f342 100644
--- a/persistence-modules/spring-hibernate-5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaIntegrationTest.java
+++ b/persistence-modules/spring-hibernate-5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaIntegrationTest.java
@@ -8,6 +8,7 @@ import java.util.List;
import org.hibernate.Session;
import org.hibernate.Transaction;
+import org.junit.Ignore;
import org.junit.Test;
import com.baeldung.hibernate.criteria.model.Item;
@@ -24,6 +25,7 @@ public class HibernateCriteriaIntegrationTest {
final private ApplicationView av = new ApplicationView();
@Test
+ @Ignore
public void testPerformanceOfCriteria() {
assertFalse(av.checkIfCriteriaTimeLower());
}
From 71fecd658963941c694f0528e981b2f88441999d Mon Sep 17 00:00:00 2001
From: Philippe
Date: Sun, 29 Mar 2020 11:49:46 -0300
Subject: [PATCH 043/187] [BAEL-3793][BAEL-3935] Code snippets
---
terraform/best-practices/README.md | 10 +++
.../best-practices/ec2-simple/.gitignore | 4 ++
terraform/best-practices/ec2-simple/SETUP.md | 23 +++++++
terraform/best-practices/ec2-simple/main.tf | 33 +++++++++
.../best-practices/ec2-simple/providers.tf | 6 ++
.../best-practices/ec2-simple/variables.tf | 15 ++++
terraform/best-practices/k8s-basic/.gitignore | 4 ++
terraform/best-practices/k8s-basic/SETUP.md | 15 ++++
terraform/best-practices/k8s-basic/main.tf | 12 ++++
.../best-practices/k8s-basic/providers.tf | 6 ++
.../best-practices/k8s-basic/variables.tf | 9 +++
.../best-practices/k8s-modules/.gitignore | 4 ++
terraform/best-practices/k8s-modules/SETUP.md | 21 ++++++
terraform/best-practices/k8s-modules/main.tf | 27 ++++++++
.../k8s-modules/modules/SvcCustomer/main.tf | 68 ++++++++++++++++++
.../modules/SvcCustomer/outputs.tf | 3 +
.../modules/SvcCustomer/variables.tf | 5 ++
.../k8s-modules/modules/SvcFeedback/main.tf | 69 +++++++++++++++++++
.../modules/SvcFeedback/outputs.tf | 3 +
.../modules/SvcFeedback/variables.tf | 5 ++
.../ingress/www.petshop.com.br/main.tf | 41 +++++++++++
.../ingress/www.petshop.com.br/outputs.tf | 5 ++
.../ingress/www.petshop.com.br/variables.tf | 20 ++++++
.../best-practices/k8s-modules/provider.tf | 13 ++++
terraform/hello-terraform/.gitignore | 6 ++
terraform/hello-terraform/main.tf | 7 ++
26 files changed, 434 insertions(+)
create mode 100644 terraform/best-practices/README.md
create mode 100644 terraform/best-practices/ec2-simple/.gitignore
create mode 100644 terraform/best-practices/ec2-simple/SETUP.md
create mode 100644 terraform/best-practices/ec2-simple/main.tf
create mode 100644 terraform/best-practices/ec2-simple/providers.tf
create mode 100644 terraform/best-practices/ec2-simple/variables.tf
create mode 100644 terraform/best-practices/k8s-basic/.gitignore
create mode 100644 terraform/best-practices/k8s-basic/SETUP.md
create mode 100644 terraform/best-practices/k8s-basic/main.tf
create mode 100644 terraform/best-practices/k8s-basic/providers.tf
create mode 100644 terraform/best-practices/k8s-basic/variables.tf
create mode 100644 terraform/best-practices/k8s-modules/.gitignore
create mode 100644 terraform/best-practices/k8s-modules/SETUP.md
create mode 100644 terraform/best-practices/k8s-modules/main.tf
create mode 100644 terraform/best-practices/k8s-modules/modules/SvcCustomer/main.tf
create mode 100644 terraform/best-practices/k8s-modules/modules/SvcCustomer/outputs.tf
create mode 100644 terraform/best-practices/k8s-modules/modules/SvcCustomer/variables.tf
create mode 100644 terraform/best-practices/k8s-modules/modules/SvcFeedback/main.tf
create mode 100644 terraform/best-practices/k8s-modules/modules/SvcFeedback/outputs.tf
create mode 100644 terraform/best-practices/k8s-modules/modules/SvcFeedback/variables.tf
create mode 100644 terraform/best-practices/k8s-modules/modules/ingress/www.petshop.com.br/main.tf
create mode 100644 terraform/best-practices/k8s-modules/modules/ingress/www.petshop.com.br/outputs.tf
create mode 100644 terraform/best-practices/k8s-modules/modules/ingress/www.petshop.com.br/variables.tf
create mode 100644 terraform/best-practices/k8s-modules/provider.tf
create mode 100644 terraform/hello-terraform/.gitignore
create mode 100644 terraform/hello-terraform/main.tf
diff --git a/terraform/best-practices/README.md b/terraform/best-practices/README.md
new file mode 100644
index 0000000000..fd488b1afb
--- /dev/null
+++ b/terraform/best-practices/README.md
@@ -0,0 +1,10 @@
+# Terraform Sample Code
+
+This folder contains Terraform project samples that illustrates topics covered in the
+"Best practices when using Terraform" article. Setup instructions are available in each sample's folder.
+
+List of available samples:
+
+ * k8s-basic: "Hello world" project that just connects to a Kubernetes cluster and create a new namespace.
+ * ec2-basic: "Hello world" project that creates a single EC2 instance
+ * k8s-modules: A more elaborate sample that creates a simple set of services in a Kubernetes cluster
diff --git a/terraform/best-practices/ec2-simple/.gitignore b/terraform/best-practices/ec2-simple/.gitignore
new file mode 100644
index 0000000000..a70da3ca16
--- /dev/null
+++ b/terraform/best-practices/ec2-simple/.gitignore
@@ -0,0 +1,4 @@
+*.tfvars
+*.tfstate
+*.tfstate.backup
+.terraform
diff --git a/terraform/best-practices/ec2-simple/SETUP.md b/terraform/best-practices/ec2-simple/SETUP.md
new file mode 100644
index 0000000000..3f906b6933
--- /dev/null
+++ b/terraform/best-practices/ec2-simple/SETUP.md
@@ -0,0 +1,23 @@
+# EC2 Basic Sample
+
+This Terraform sample project creates a single EC2 instance in the configured region.
+
+IMPORTANT NOTICE: In order to run this sample you must have an active AWS Account. As you probably know, creating resources on AWS
+may result in additional charges in your bill. We recommend creating a test account to run this test as you can then use AWS's free tier
+to play around. When finished, ALWAYS REMEMBER TO DESTROY YOUR RESOURCES !!!
+
+# Setup instructions
+
+1. Make sure you have a working AWS environment. Use a simple command such as _aws ec2 describe-instances_ and check its output.
+ If you get a list of existing EC2 instances, you're good to go. Otherwise, please refer to AWS documentation in order to setup your CLI.
+2. Download the Terraform package for your environment from Hashicorp's site. Unzip it and put the _terraform_ binary somewhere
+ in the OS's PATH.
+3. Open a command prompt and _cd_ into this folder
+4. Run the following commands:
+'''
+ $ terraform init
+ $ terraform apply -auto-approve
+'''
+5. Wait until Terraform create all resources and run _aws ec2 describe-instances_. The output should list the newly creates EC2 instance
+6. Run _terraform destroy_ to remove the previously creates namespace.
+
diff --git a/terraform/best-practices/ec2-simple/main.tf b/terraform/best-practices/ec2-simple/main.tf
new file mode 100644
index 0000000000..57fb9d1757
--- /dev/null
+++ b/terraform/best-practices/ec2-simple/main.tf
@@ -0,0 +1,33 @@
+#
+# Resource definitions
+#
+
+data "aws_ami" "apache" {
+ filter {
+ name = "name"
+ values = [var.ami_name]
+ }
+
+ filter {
+ name = "virtualization-type"
+ values = ["hvm"]
+ }
+
+ owners = [var.ami_owner]
+
+ most_recent = true
+}
+
+resource "aws_instance" "web" {
+ ami = data.aws_ami.apache.id
+ instance_type = "t2.micro"
+ subnet_id = aws_subnet.frontend.id
+}
+resource "aws_subnet" "frontend" {
+ vpc_id = aws_vpc.apps.id
+ cidr_block = "10.0.1.0/24"
+}
+
+resource "aws_vpc" "apps" {
+ cidr_block = "10.0.0.0/16"
+}
diff --git a/terraform/best-practices/ec2-simple/providers.tf b/terraform/best-practices/ec2-simple/providers.tf
new file mode 100644
index 0000000000..fa5826b067
--- /dev/null
+++ b/terraform/best-practices/ec2-simple/providers.tf
@@ -0,0 +1,6 @@
+#
+# Providers definitions
+#
+provider "aws" {
+ version = "~> 2.53"
+}
\ No newline at end of file
diff --git a/terraform/best-practices/ec2-simple/variables.tf b/terraform/best-practices/ec2-simple/variables.tf
new file mode 100644
index 0000000000..2a7fddcd33
--- /dev/null
+++ b/terraform/best-practices/ec2-simple/variables.tf
@@ -0,0 +1,15 @@
+#
+# Variables
+#
+
+variable "ami_name" {
+ type = string
+ description = "AMI name to use for our EC2 instance. Defaults to Ubuntu 18.04 (Bionic)"
+ default = "ubuntu/images/hvm-ssd/ubuntu-bionic-18.04-amd64-*"
+}
+
+variable "ami_owner" {
+ type = string
+ description = "AMI Owner ID to use for our EC2 instance. Defaults to 099720109477 (Canonical)"
+ default = "099720109477"
+}
\ No newline at end of file
diff --git a/terraform/best-practices/k8s-basic/.gitignore b/terraform/best-practices/k8s-basic/.gitignore
new file mode 100644
index 0000000000..a70da3ca16
--- /dev/null
+++ b/terraform/best-practices/k8s-basic/.gitignore
@@ -0,0 +1,4 @@
+*.tfvars
+*.tfstate
+*.tfstate.backup
+.terraform
diff --git a/terraform/best-practices/k8s-basic/SETUP.md b/terraform/best-practices/k8s-basic/SETUP.md
new file mode 100644
index 0000000000..479bb75274
--- /dev/null
+++ b/terraform/best-practices/k8s-basic/SETUP.md
@@ -0,0 +1,15 @@
+# Setup instructions
+
+1. Mak sure you have a working Kubernetes environment. Use a simple command such as _kubectl get nodes_ and check its output.
+ If you get a list of nodes that contains at least one _ready_ module, you're good to go
+2. Download the Terraform package for your environment from Hashicorp's site. Unzip it and put the _terraform_ binary somewhere
+ in the OS's PATH.
+3. Open a command prompt and _cd_ into this folder
+4. Run the following commands:
+'''
+ $ terraform init
+ $ terraform apply -auto-approve
+'''
+5. Wait until Terraform create all resources and run _kubectl get namespaces_. The output should now have a new "hello-terraform" namespace.
+6. Run _terraform destroy_ to remove the previously creates namespace.
+
diff --git a/terraform/best-practices/k8s-basic/main.tf b/terraform/best-practices/k8s-basic/main.tf
new file mode 100644
index 0000000000..5eb3749930
--- /dev/null
+++ b/terraform/best-practices/k8s-basic/main.tf
@@ -0,0 +1,12 @@
+#
+# Resource definitions
+#
+
+resource "kubernetes_namespace" "hello" {
+ metadata {
+ labels = {
+ terraform = "true"
+ }
+ name = var.namespace_name
+ }
+}
\ No newline at end of file
diff --git a/terraform/best-practices/k8s-basic/providers.tf b/terraform/best-practices/k8s-basic/providers.tf
new file mode 100644
index 0000000000..385f857a11
--- /dev/null
+++ b/terraform/best-practices/k8s-basic/providers.tf
@@ -0,0 +1,6 @@
+#
+# Providers definitions
+#
+provider "kubernetes" {
+ version = "~> 1.11"
+}
\ No newline at end of file
diff --git a/terraform/best-practices/k8s-basic/variables.tf b/terraform/best-practices/k8s-basic/variables.tf
new file mode 100644
index 0000000000..b9217079bf
--- /dev/null
+++ b/terraform/best-practices/k8s-basic/variables.tf
@@ -0,0 +1,9 @@
+#
+# Variables
+#
+
+variable "namespace_name" {
+ type = string
+ description = "Name to use for the created namespace"
+ default = "hello-terraform"
+}
\ No newline at end of file
diff --git a/terraform/best-practices/k8s-modules/.gitignore b/terraform/best-practices/k8s-modules/.gitignore
new file mode 100644
index 0000000000..a70da3ca16
--- /dev/null
+++ b/terraform/best-practices/k8s-modules/.gitignore
@@ -0,0 +1,4 @@
+*.tfvars
+*.tfstate
+*.tfstate.backup
+.terraform
diff --git a/terraform/best-practices/k8s-modules/SETUP.md b/terraform/best-practices/k8s-modules/SETUP.md
new file mode 100644
index 0000000000..b7e4c2764d
--- /dev/null
+++ b/terraform/best-practices/k8s-modules/SETUP.md
@@ -0,0 +1,21 @@
+# Kubernetes multimodule sample
+
+This sample deploys two services behind a Kubernetes ingress.
+
+# Setup instructions
+
+1. Mak sure you have a working Kubernetes environment. Use a simple command such as _kubectl get nodes_ and check its output.
+ If you get a list of nodes that contains at least one _ready_ module, you're good to go
+2. Download the Terraform package for your environment from Hashicorp's site. Unzip it and put the _terraform_ binary somewhere
+ in the OS's PATH.
+3. Open a command prompt and _cd_ into this folder
+4. Run the following commands:
+'''
+ $ terraform init
+ $ terraform apply -auto-approve
+'''
+5. Wait until Terraform create all resources and run _kubectl get services_. The output should now have a few services.
+6. Run _terraform destroy_ to remove the previously creates namespace.
+
+
+
diff --git a/terraform/best-practices/k8s-modules/main.tf b/terraform/best-practices/k8s-modules/main.tf
new file mode 100644
index 0000000000..86426b33db
--- /dev/null
+++ b/terraform/best-practices/k8s-modules/main.tf
@@ -0,0 +1,27 @@
+/*
+ * Top-level definitions
+ */
+
+//================================================================== Ingress
+
+module "ingress_www_petshop_com_br" {
+ source = "./modules/ingress/www.petshop.com.br"
+ ingress_host = "www.petshop.com.br"
+}
+
+//================================================================== Deployments
+
+module "SvcCustomer" {
+ source = "./modules/SvcCustomer"
+}
+
+module "SvcFeedback" {
+ source = "./modules/SvcFeedback"
+}
+
+
+
+
+
+
+
diff --git a/terraform/best-practices/k8s-modules/modules/SvcCustomer/main.tf b/terraform/best-practices/k8s-modules/modules/SvcCustomer/main.tf
new file mode 100644
index 0000000000..1ca0c91545
--- /dev/null
+++ b/terraform/best-practices/k8s-modules/modules/SvcCustomer/main.tf
@@ -0,0 +1,68 @@
+/*
+ * SvcCustomer deployment resources
+ */
+
+resource "kubernetes_deployment" "SvcCustomer" {
+
+ metadata {
+ name = "svccustomer"
+ labels = {
+ app = "SvcCustomer"
+ }
+ }
+
+ spec {
+ replicas = 1
+
+ selector {
+ match_labels = {
+ app = "SvcCustomer"
+ }
+ }
+
+ template {
+ metadata {
+ labels = {
+ app = "SvcCustomer"
+ }
+ }
+
+ spec {
+ image_pull_secrets {
+ name = "docker-config"
+ }
+
+
+ container {
+ image = "inanimate/echo-server"
+ name = "svccustomer-httpd"
+ env {
+ name = "PORT"
+ value = "80"
+ }
+ }
+ }
+ }
+ }
+}
+
+resource "kubernetes_service" "SvcCustomer" {
+ metadata {
+ name = "svccustomer"
+ }
+
+ spec {
+
+ selector = {
+ app = "SvcCustomer"
+ }
+
+ session_affinity = "ClientIP"
+ port {
+ port = 80
+ }
+
+ //type = "LoadBalancer"
+ }
+ }
+
\ No newline at end of file
diff --git a/terraform/best-practices/k8s-modules/modules/SvcCustomer/outputs.tf b/terraform/best-practices/k8s-modules/modules/SvcCustomer/outputs.tf
new file mode 100644
index 0000000000..8a37fdf375
--- /dev/null
+++ b/terraform/best-practices/k8s-modules/modules/SvcCustomer/outputs.tf
@@ -0,0 +1,3 @@
+/*
+ * SvcCustomer output values
+ */
diff --git a/terraform/best-practices/k8s-modules/modules/SvcCustomer/variables.tf b/terraform/best-practices/k8s-modules/modules/SvcCustomer/variables.tf
new file mode 100644
index 0000000000..3dfcfcd264
--- /dev/null
+++ b/terraform/best-practices/k8s-modules/modules/SvcCustomer/variables.tf
@@ -0,0 +1,5 @@
+/*
+ * SvcCustomer deployment variables
+ */
+
+
\ No newline at end of file
diff --git a/terraform/best-practices/k8s-modules/modules/SvcFeedback/main.tf b/terraform/best-practices/k8s-modules/modules/SvcFeedback/main.tf
new file mode 100644
index 0000000000..0f84c9163e
--- /dev/null
+++ b/terraform/best-practices/k8s-modules/modules/SvcFeedback/main.tf
@@ -0,0 +1,69 @@
+/*
+ * SvcFeedback deployment resources
+ */
+
+resource "kubernetes_deployment" "SvcFeedback" {
+
+ metadata {
+ name = "svcfeedback"
+ labels = {
+ app = "SvcFeedback"
+ }
+ }
+
+ spec {
+ replicas = 1
+
+ selector {
+ match_labels = {
+ app = "SvcFeedback"
+ }
+ }
+
+ template {
+ metadata {
+ labels = {
+ app = "SvcFeedback"
+ }
+ }
+
+ spec {
+ image_pull_secrets {
+ name = "docker-config"
+ }
+
+
+ container {
+ image = "inanimate/echo-server"
+ name = "svcfeedback-httpd"
+ env {
+ name = "PORT"
+ value = "80"
+ }
+ }
+
+ }
+ }
+ }
+}
+
+resource "kubernetes_service" "SvcFeedback" {
+ metadata {
+ name = "svcfeedback"
+ }
+
+ spec {
+
+ selector = {
+ app = "SvcFeedback"
+ }
+
+ session_affinity = "ClientIP"
+ port {
+ port = 80
+ }
+
+ //type = "LoadBalancer"
+ }
+ }
+
\ No newline at end of file
diff --git a/terraform/best-practices/k8s-modules/modules/SvcFeedback/outputs.tf b/terraform/best-practices/k8s-modules/modules/SvcFeedback/outputs.tf
new file mode 100644
index 0000000000..e08c17d4b4
--- /dev/null
+++ b/terraform/best-practices/k8s-modules/modules/SvcFeedback/outputs.tf
@@ -0,0 +1,3 @@
+/*
+ * SvcFeedback output values
+ */
diff --git a/terraform/best-practices/k8s-modules/modules/SvcFeedback/variables.tf b/terraform/best-practices/k8s-modules/modules/SvcFeedback/variables.tf
new file mode 100644
index 0000000000..d8076d41a4
--- /dev/null
+++ b/terraform/best-practices/k8s-modules/modules/SvcFeedback/variables.tf
@@ -0,0 +1,5 @@
+/*
+ * SvcFeedback deployment variables
+ */
+
+
\ No newline at end of file
diff --git a/terraform/best-practices/k8s-modules/modules/ingress/www.petshop.com.br/main.tf b/terraform/best-practices/k8s-modules/modules/ingress/www.petshop.com.br/main.tf
new file mode 100644
index 0000000000..0dbda48981
--- /dev/null
+++ b/terraform/best-practices/k8s-modules/modules/ingress/www.petshop.com.br/main.tf
@@ -0,0 +1,41 @@
+/*
+ * Kubernetes Ingress module
+ */
+locals {
+ iname = var.ingress_name == "" ? join("-",["ingress",sha1(uuid())]) : var.ingress_name
+}
+
+resource "kubernetes_ingress" "ingress" {
+ metadata {
+ name = local.iname
+ annotations = map(
+ "nginx.ingress.kubernetes.io/rewrite-target","/"
+ )
+ }
+ spec {
+ rule {
+ http {
+ path {
+ backend {
+ service_name = "svccustomer"
+ service_port = 80
+ }
+ path = "/customers"
+ }
+ path {
+ backend {
+ service_name = "svcfeedback"
+ service_port = 80
+ }
+ path = "/feedback"
+ }
+ }
+ }
+/*
+ tls {
+ secret_name = "tls-secret"
+ }
+*/
+ }
+}
+
diff --git a/terraform/best-practices/k8s-modules/modules/ingress/www.petshop.com.br/outputs.tf b/terraform/best-practices/k8s-modules/modules/ingress/www.petshop.com.br/outputs.tf
new file mode 100644
index 0000000000..e604417b05
--- /dev/null
+++ b/terraform/best-practices/k8s-modules/modules/ingress/www.petshop.com.br/outputs.tf
@@ -0,0 +1,5 @@
+/*
+ * Output variables
+ */
+
+
diff --git a/terraform/best-practices/k8s-modules/modules/ingress/www.petshop.com.br/variables.tf b/terraform/best-practices/k8s-modules/modules/ingress/www.petshop.com.br/variables.tf
new file mode 100644
index 0000000000..9b06128ec5
--- /dev/null
+++ b/terraform/best-practices/k8s-modules/modules/ingress/www.petshop.com.br/variables.tf
@@ -0,0 +1,20 @@
+/*
+ * Kubernetes Ingress module
+ */
+
+
+variable "ingress_name" {
+ type = string
+ description = "Ingress name. Defaults to a random name."
+ default = ""
+}
+
+variable "ingress_host" {
+ type = string
+ description = "Ingress hostname"
+ default = "www.petshop.com.br"
+}
+
+
+
+
diff --git a/terraform/best-practices/k8s-modules/provider.tf b/terraform/best-practices/k8s-modules/provider.tf
new file mode 100644
index 0000000000..bb90d66ecf
--- /dev/null
+++ b/terraform/best-practices/k8s-modules/provider.tf
@@ -0,0 +1,13 @@
+#
+# Provider configurations
+# This file will *NOT* be overwriten upon regeneration, so it's safe
+# to add your own customizations
+#
+
+provider "kubernetes" {
+ version = "~> 1.10"
+}
+
+provider "random" {
+ version = "~> 2.2"
+}
\ No newline at end of file
diff --git a/terraform/hello-terraform/.gitignore b/terraform/hello-terraform/.gitignore
new file mode 100644
index 0000000000..452502c50f
--- /dev/null
+++ b/terraform/hello-terraform/.gitignore
@@ -0,0 +1,6 @@
+*.tfvars
+*.tfstate
+*.tfstate.backup
+.terraform
+hello.txt
+
diff --git a/terraform/hello-terraform/main.tf b/terraform/hello-terraform/main.tf
new file mode 100644
index 0000000000..d6a726fa36
--- /dev/null
+++ b/terraform/hello-terraform/main.tf
@@ -0,0 +1,7 @@
+provider "local" {
+ version = "~> 1.4"
+}
+resource "local_file" "hello" {
+ content = "Hello, Terraform"
+ filename = "hello.txt"
+}
From 4382852a1731d9d06f838219ec176ddf89c04d3d Mon Sep 17 00:00:00 2001
From: Krzysiek
Date: Sun, 29 Mar 2020 19:00:40 +0200
Subject: [PATCH 044/187] JAVA-43: Upgrade spring-security-modules to Spring
Boot 2
---
spring-security-modules/spring-security-acl/pom.xml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/spring-security-modules/spring-security-acl/pom.xml b/spring-security-modules/spring-security-acl/pom.xml
index 3c613f9d92..5c04aaa9ca 100644
--- a/spring-security-modules/spring-security-acl/pom.xml
+++ b/spring-security-modules/spring-security-acl/pom.xml
@@ -10,9 +10,9 @@
com.baeldung
- parent-boot-1
+ parent-boot-2
0.0.1-SNAPSHOT
- ../../parent-boot-1
+ ../../parent-boot-2
From 65e21d3f6a394cbfc34f6c6d8b49d92a02a4aa9e Mon Sep 17 00:00:00 2001
From: Seun Matt
Date: Sun, 29 Mar 2020 21:36:54 +0100
Subject: [PATCH 045/187] example code for BAEL-3749 (#8815)
* example code for BAEL-3749
* added live test
* added live test
* improved exception handling in response log filter
* propage exception in example code
* updated repo with upstream
* added example code for BAEL-3293
* updated the example code for BAEL-3749
* updated the example code for BAEL-3749
* updated the example code for BAEL-3749
* updated the example code for BAEL-3749
---
cas/cas-secured-app/pom.xml | 8 +-
.../CasSecuredAppApplication.java | 91 ------
.../cassecuredapp/CasSecuredApplication.java | 97 +++++++
.../cassecuredapp/config/SecurityConfig.java | 83 ------
.../config/WebSecurityConfig.java | 79 ++++++
.../controllers/AuthController.java | 29 +-
.../controllers/IndexController.java | 8 +-
.../controllers/SecuredController.java | 30 ++
.../controllers/SecuredPageController.java | 24 --
.../src/main/resources/application.properties | 3 +-
...CasSecuredApplicationIntegrationTest.java} | 2 +-
cas/cas-server/.factorypath | 228 ----------------
cas/cas-server/.gitignore | 7 +
cas/cas-server/.mergify.yml | 32 +++
cas/cas-server/.travis.yml | 62 +++++
cas/cas-server/Dockerfile | 40 +++
cas/cas-server/README.md | 151 ++++++----
cas/cas-server/build.cmd | 102 -------
cas/cas-server/build.gradle | 106 +++++++
cas/cas-server/build.sh | 189 -------------
cas/cas-server/docker-build.sh | 10 +
cas/cas-server/docker-compose.yml | 7 +
cas/cas-server/docker-push.sh | 12 +
cas/cas-server/docker-run.sh | 7 +
cas/cas-server/etc/cas/config/application.yml | 2 -
cas/cas-server/etc/cas/config/cas.properties | 9 +-
cas/cas-server/etc/cas/config/log4j2.xml | 120 ++++----
cas/cas-server/etc/cas/saml/.gitkeep | 1 +
cas/cas-server/etc/cas/services/.donotdel | 0
cas/cas-server/etc/cas/thekeystore | Bin 0 -> 2266 bytes
cas/cas-server/gradle.properties | 28 ++
cas/cas-server/gradle/dockerjib.gradle | 52 ++++
cas/cas-server/gradle/springboot.gradle | 24 ++
cas/cas-server/gradle/tasks.gradle | 258 ++++++++++++++++++
.../gradle/wrapper/gradle-wrapper.properties | 5 +
cas/cas-server/gradlew | 188 +++++++++++++
cas/cas-server/gradlew.bat | 100 +++++++
cas/cas-server/maven/maven-wrapper.jar | Bin 71910 -> 0 bytes
cas/cas-server/maven/maven-wrapper.properties | 3 -
cas/cas-server/mvnw | 234 ----------------
cas/cas-server/mvnw.bat | 174 ------------
cas/cas-server/pom.xml | 208 --------------
cas/cas-server/settings.gradle | 1 +
.../src/main/jib/docker/entrypoint.sh | 22 ++
.../src/main/resources/application.properties | 136 +--------
.../src/main/resources/cas.properties | 9 -
.../create_test_db_and_users_tbl.sql | 12 +-
.../resources/etc/cas/config/application.yml | 2 -
.../resources/etc/cas/config/cas.properties | 18 +-
.../main/resources/etc/cas/config/log4j2.xml | 117 --------
.../etc/cas/services/casSecuredApp-8900.json | 8 +
.../src/main/resources/etc/cas/thekeystore | Bin 2258 -> 2251 bytes
.../main/resources/etc/cas/thekeystore.crt | Bin 901 -> 0 bytes
cas/cas-server/src/main/resources/log4j2.xml | 117 --------
.../services/casSecuredApp-19991.json | 8 -
cas/pom.xml | 23 --
pom.xml | 2 -
57 files changed, 1390 insertions(+), 1898 deletions(-)
delete mode 100644 cas/cas-secured-app/src/main/java/com/baeldung/cassecuredapp/CasSecuredAppApplication.java
create mode 100644 cas/cas-secured-app/src/main/java/com/baeldung/cassecuredapp/CasSecuredApplication.java
delete mode 100644 cas/cas-secured-app/src/main/java/com/baeldung/cassecuredapp/config/SecurityConfig.java
create mode 100644 cas/cas-secured-app/src/main/java/com/baeldung/cassecuredapp/config/WebSecurityConfig.java
create mode 100644 cas/cas-secured-app/src/main/java/com/baeldung/cassecuredapp/controllers/SecuredController.java
delete mode 100644 cas/cas-secured-app/src/main/java/com/baeldung/cassecuredapp/controllers/SecuredPageController.java
rename cas/cas-secured-app/src/test/java/com/baeldung/cassecuredapp/{CasSecuredAppApplicationIntegrationTest.java => CasSecuredApplicationIntegrationTest.java} (84%)
delete mode 100644 cas/cas-server/.factorypath
mode change 100644 => 100755 cas/cas-server/.gitignore
create mode 100644 cas/cas-server/.mergify.yml
create mode 100644 cas/cas-server/.travis.yml
create mode 100644 cas/cas-server/Dockerfile
delete mode 100644 cas/cas-server/build.cmd
create mode 100644 cas/cas-server/build.gradle
delete mode 100644 cas/cas-server/build.sh
create mode 100755 cas/cas-server/docker-build.sh
create mode 100644 cas/cas-server/docker-compose.yml
create mode 100755 cas/cas-server/docker-push.sh
create mode 100755 cas/cas-server/docker-run.sh
delete mode 100644 cas/cas-server/etc/cas/config/application.yml
create mode 100644 cas/cas-server/etc/cas/saml/.gitkeep
create mode 100644 cas/cas-server/etc/cas/services/.donotdel
create mode 100644 cas/cas-server/etc/cas/thekeystore
create mode 100644 cas/cas-server/gradle.properties
create mode 100644 cas/cas-server/gradle/dockerjib.gradle
create mode 100644 cas/cas-server/gradle/springboot.gradle
create mode 100644 cas/cas-server/gradle/tasks.gradle
create mode 100644 cas/cas-server/gradle/wrapper/gradle-wrapper.properties
create mode 100755 cas/cas-server/gradlew
create mode 100644 cas/cas-server/gradlew.bat
delete mode 100644 cas/cas-server/maven/maven-wrapper.jar
delete mode 100644 cas/cas-server/maven/maven-wrapper.properties
delete mode 100644 cas/cas-server/mvnw
delete mode 100644 cas/cas-server/mvnw.bat
create mode 100644 cas/cas-server/settings.gradle
create mode 100755 cas/cas-server/src/main/jib/docker/entrypoint.sh
delete mode 100644 cas/cas-server/src/main/resources/cas.properties
delete mode 100644 cas/cas-server/src/main/resources/etc/cas/config/application.yml
delete mode 100644 cas/cas-server/src/main/resources/etc/cas/config/log4j2.xml
create mode 100644 cas/cas-server/src/main/resources/etc/cas/services/casSecuredApp-8900.json
delete mode 100644 cas/cas-server/src/main/resources/etc/cas/thekeystore.crt
delete mode 100644 cas/cas-server/src/main/resources/log4j2.xml
delete mode 100644 cas/cas-server/src/main/resources/services/casSecuredApp-19991.json
diff --git a/cas/cas-secured-app/pom.xml b/cas/cas-secured-app/pom.xml
index 8e6f28e3a8..426d65c32b 100644
--- a/cas/cas-secured-app/pom.xml
+++ b/cas/cas-secured-app/pom.xml
@@ -11,11 +11,15 @@
com.baeldung
- parent-boot-1
+ parent-boot-2
0.0.1-SNAPSHOT
- ../../parent-boot-1
+ ../../parent-boot-2
+
+ 2.2.6.RELEASE
+
+
org.springframework.boot
diff --git a/cas/cas-secured-app/src/main/java/com/baeldung/cassecuredapp/CasSecuredAppApplication.java b/cas/cas-secured-app/src/main/java/com/baeldung/cassecuredapp/CasSecuredAppApplication.java
deleted file mode 100644
index 25cbb9bc9b..0000000000
--- a/cas/cas-secured-app/src/main/java/com/baeldung/cassecuredapp/CasSecuredAppApplication.java
+++ /dev/null
@@ -1,91 +0,0 @@
-package com.baeldung.cassecuredapp;
-
-import org.jasig.cas.client.session.SingleSignOutFilter;
-import org.jasig.cas.client.session.SingleSignOutHttpSessionListener;
-import org.jasig.cas.client.validation.Cas30ServiceTicketValidator;
-import org.jasig.cas.client.validation.TicketValidator;
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Primary;
-import org.springframework.context.event.EventListener;
-import org.springframework.security.cas.ServiceProperties;
-import org.springframework.security.cas.authentication.CasAuthenticationProvider;
-import org.springframework.security.cas.web.CasAuthenticationEntryPoint;
-import org.springframework.security.core.authority.AuthorityUtils;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.security.core.userdetails.User;
-import org.springframework.security.web.AuthenticationEntryPoint;
-import org.springframework.security.web.authentication.logout.LogoutFilter;
-import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
-
-import javax.servlet.http.HttpSessionEvent;
-
-@SpringBootApplication
-public class CasSecuredAppApplication {
-
- public static void main(String[] args) {
- SpringApplication.run(CasSecuredAppApplication.class, args);
- }
-
- @Bean
- public ServiceProperties serviceProperties() {
- ServiceProperties serviceProperties = new ServiceProperties();
- serviceProperties.setService("http://localhost:9000/login/cas");
- serviceProperties.setSendRenew(false);
- return serviceProperties;
- }
-
- @Bean
- @Primary
- public AuthenticationEntryPoint authenticationEntryPoint(ServiceProperties sP) {
- CasAuthenticationEntryPoint entryPoint = new CasAuthenticationEntryPoint();
- entryPoint.setLoginUrl("https://localhost:6443/cas/login");
- entryPoint.setServiceProperties(sP);
- return entryPoint;
- }
-
- @Bean
- public TicketValidator ticketValidator() {
- return new Cas30ServiceTicketValidator("https://localhost:6443/cas");
- }
-
- @Bean
- public CasAuthenticationProvider casAuthenticationProvider() {
- CasAuthenticationProvider provider = new CasAuthenticationProvider();
- provider.setServiceProperties(serviceProperties());
- provider.setTicketValidator(ticketValidator());
- provider.setUserDetailsService((s) -> new User("test@test.com", "smatt",
- true, true, true, true,
- AuthorityUtils.createAuthorityList("ROLE_ADMIN")));
- provider.setKey("CAS_PROVIDER_LOCALHOST_9000");
- return provider;
- }
-
-
- @Bean
- public SecurityContextLogoutHandler securityContextLogoutHandler() {
- return new SecurityContextLogoutHandler();
- }
-
- @Bean
- public LogoutFilter logoutFilter() {
- LogoutFilter logoutFilter = new LogoutFilter(
- "https://localhost:6443/cas/logout", securityContextLogoutHandler());
- logoutFilter.setFilterProcessesUrl("/logout/cas");
- return logoutFilter;
- }
-
- @Bean
- public SingleSignOutFilter singleSignOutFilter() {
- SingleSignOutFilter singleSignOutFilter = new SingleSignOutFilter();
- singleSignOutFilter.setCasServerUrlPrefix("https://localhost:6443/cas");
- singleSignOutFilter.setIgnoreInitConfiguration(true);
- return singleSignOutFilter;
- }
-
- @EventListener
- public SingleSignOutHttpSessionListener singleSignOutHttpSessionListener(HttpSessionEvent event) {
- return new SingleSignOutHttpSessionListener();
- }
-}
diff --git a/cas/cas-secured-app/src/main/java/com/baeldung/cassecuredapp/CasSecuredApplication.java b/cas/cas-secured-app/src/main/java/com/baeldung/cassecuredapp/CasSecuredApplication.java
new file mode 100644
index 0000000000..4a2c609758
--- /dev/null
+++ b/cas/cas-secured-app/src/main/java/com/baeldung/cassecuredapp/CasSecuredApplication.java
@@ -0,0 +1,97 @@
+package com.baeldung.cassecuredapp;
+
+import org.jasig.cas.client.session.SingleSignOutFilter;
+import org.jasig.cas.client.session.SingleSignOutHttpSessionListener;
+import org.jasig.cas.client.validation.Cas30ServiceTicketValidator;
+import org.jasig.cas.client.validation.TicketValidator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Primary;
+import org.springframework.context.event.EventListener;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.cas.ServiceProperties;
+import org.springframework.security.cas.authentication.CasAuthenticationProvider;
+import org.springframework.security.cas.web.CasAuthenticationEntryPoint;
+import org.springframework.security.cas.web.CasAuthenticationFilter;
+import org.springframework.security.core.authority.AuthorityUtils;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.security.web.AuthenticationEntryPoint;
+import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
+import org.springframework.security.web.authentication.logout.LogoutFilter;
+import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
+
+import javax.servlet.http.HttpSessionEvent;
+
+@SpringBootApplication
+public class CasSecuredApplication {
+
+ private static final Logger logger = LoggerFactory.getLogger(CasSecuredApplication.class);
+
+ public static void main(String... args) {
+ SpringApplication.run(CasSecuredApplication.class, args);
+ }
+
+ @Bean
+ public CasAuthenticationFilter casAuthenticationFilter(
+ AuthenticationManager authenticationManager,
+ ServiceProperties serviceProperties) throws Exception {
+ CasAuthenticationFilter filter = new CasAuthenticationFilter();
+ filter.setAuthenticationManager(authenticationManager);
+ filter.setServiceProperties(serviceProperties);
+ return filter;
+ }
+
+ @Bean
+ public ServiceProperties serviceProperties() {
+ logger.info("service properties");
+ ServiceProperties serviceProperties = new ServiceProperties();
+ serviceProperties.setService("http://cas-client:8900/login/cas");
+ serviceProperties.setSendRenew(false);
+ return serviceProperties;
+ }
+
+ @Bean
+ public TicketValidator ticketValidator() {
+ return new Cas30ServiceTicketValidator("https://localhost:8443");
+ }
+
+ @Bean
+ public CasAuthenticationProvider casAuthenticationProvider(
+ TicketValidator ticketValidator,
+ ServiceProperties serviceProperties) {
+ CasAuthenticationProvider provider = new CasAuthenticationProvider();
+ provider.setServiceProperties(serviceProperties);
+ provider.setTicketValidator(ticketValidator);
+ provider.setUserDetailsService(
+ s -> new User("test@test.com", "Mellon", true, true, true, true,
+ AuthorityUtils.createAuthorityList("ROLE_ADMIN")));
+ provider.setKey("CAS_PROVIDER_LOCALHOST_8900");
+ return provider;
+ }
+
+
+ @Bean
+ public SecurityContextLogoutHandler securityContextLogoutHandler() {
+ return new SecurityContextLogoutHandler();
+ }
+
+ @Bean
+ public LogoutFilter logoutFilter() {
+ LogoutFilter logoutFilter = new LogoutFilter("https://localhost:8443/logout", securityContextLogoutHandler());
+ logoutFilter.setFilterProcessesUrl("/logout/cas");
+ return logoutFilter;
+ }
+
+ @Bean
+ public SingleSignOutFilter singleSignOutFilter() {
+ SingleSignOutFilter singleSignOutFilter = new SingleSignOutFilter();
+ singleSignOutFilter.setCasServerUrlPrefix("https://localhost:8443");
+ singleSignOutFilter.setLogoutCallbackPath("/exit/cas");
+ singleSignOutFilter.setIgnoreInitConfiguration(true);
+ return singleSignOutFilter;
+ }
+
+}
diff --git a/cas/cas-secured-app/src/main/java/com/baeldung/cassecuredapp/config/SecurityConfig.java b/cas/cas-secured-app/src/main/java/com/baeldung/cassecuredapp/config/SecurityConfig.java
deleted file mode 100644
index 2eabed49e1..0000000000
--- a/cas/cas-secured-app/src/main/java/com/baeldung/cassecuredapp/config/SecurityConfig.java
+++ /dev/null
@@ -1,83 +0,0 @@
-package com.baeldung.cassecuredapp.config;
-
-import org.jasig.cas.client.session.SingleSignOutFilter;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.security.authentication.AuthenticationManager;
-import org.springframework.security.authentication.AuthenticationProvider;
-import org.springframework.security.authentication.ProviderManager;
-import org.springframework.security.cas.ServiceProperties;
-import org.springframework.security.cas.authentication.CasAuthenticationProvider;
-import org.springframework.security.cas.web.CasAuthenticationFilter;
-import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
-import org.springframework.security.config.annotation.web.builders.HttpSecurity;
-import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
-import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
-import org.springframework.security.web.AuthenticationEntryPoint;
-import org.springframework.security.web.authentication.logout.LogoutFilter;
-
-import java.util.Arrays;
-
-@EnableWebSecurity
-@Configuration
-public class SecurityConfig extends WebSecurityConfigurerAdapter {
-
- private AuthenticationProvider authenticationProvider;
- private AuthenticationEntryPoint authenticationEntryPoint;
- private SingleSignOutFilter singleSignOutFilter;
- private LogoutFilter logoutFilter;
-
- @Autowired
- public SecurityConfig(CasAuthenticationProvider casAuthenticationProvider, AuthenticationEntryPoint eP,
- LogoutFilter lF
- , SingleSignOutFilter ssF
- ) {
- this.authenticationProvider = casAuthenticationProvider;
- this.authenticationEntryPoint = eP;
-
- this.logoutFilter = lF;
- this.singleSignOutFilter = ssF;
-
- }
-
- @Override
- protected void configure(HttpSecurity http) throws Exception {
- http
- .authorizeRequests()
- .regexMatchers("/secured.*", "/login")
- .authenticated()
- .and()
- .authorizeRequests()
- .regexMatchers("/")
- .permitAll()
- .and()
- .httpBasic()
- .authenticationEntryPoint(authenticationEntryPoint)
- .and()
- .logout().logoutSuccessUrl("/logout")
- .and()
- .addFilterBefore(singleSignOutFilter, CasAuthenticationFilter.class)
- .addFilterBefore(logoutFilter, LogoutFilter.class);
-
- }
-
- @Override
- protected void configure(AuthenticationManagerBuilder auth) throws Exception {
- auth.authenticationProvider(authenticationProvider);
- }
-
- @Override
- protected AuthenticationManager authenticationManager() throws Exception {
- return new ProviderManager(Arrays.asList(authenticationProvider));
- }
-
- @Bean
- public CasAuthenticationFilter casAuthenticationFilter(ServiceProperties sP) throws Exception {
- CasAuthenticationFilter filter = new CasAuthenticationFilter();
- filter.setServiceProperties(sP);
- filter.setAuthenticationManager(authenticationManager());
- return filter;
- }
-
-}
diff --git a/cas/cas-secured-app/src/main/java/com/baeldung/cassecuredapp/config/WebSecurityConfig.java b/cas/cas-secured-app/src/main/java/com/baeldung/cassecuredapp/config/WebSecurityConfig.java
new file mode 100644
index 0000000000..b0c3c68387
--- /dev/null
+++ b/cas/cas-secured-app/src/main/java/com/baeldung/cassecuredapp/config/WebSecurityConfig.java
@@ -0,0 +1,79 @@
+package com.baeldung.cassecuredapp.config;
+
+import org.jasig.cas.client.session.SingleSignOutFilter;
+import org.jasig.cas.client.validation.Cas30ServiceTicketValidator;
+import org.jasig.cas.client.validation.TicketValidator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Primary;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.ProviderManager;
+import org.springframework.security.cas.ServiceProperties;
+import org.springframework.security.cas.authentication.CasAuthenticationProvider;
+import org.springframework.security.cas.web.CasAuthenticationEntryPoint;
+import org.springframework.security.cas.web.CasAuthenticationFilter;
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.core.authority.AuthorityUtils;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.security.web.AuthenticationEntryPoint;
+import org.springframework.security.web.authentication.logout.LogoutFilter;
+
+import java.util.Collections;
+
+@EnableWebSecurity
+public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
+
+ private Logger logger = LoggerFactory.getLogger(WebSecurityConfig.class);
+ private SingleSignOutFilter singleSignOutFilter;
+ private LogoutFilter logoutFilter;
+ private CasAuthenticationProvider casAuthenticationProvider;
+ private ServiceProperties serviceProperties;
+
+ @Autowired
+ public WebSecurityConfig(SingleSignOutFilter singleSignOutFilter, LogoutFilter logoutFilter,
+ CasAuthenticationProvider casAuthenticationProvider,
+ ServiceProperties serviceProperties) {
+ this.logoutFilter = logoutFilter;
+ this.singleSignOutFilter = singleSignOutFilter;
+ this.serviceProperties = serviceProperties;
+ this.casAuthenticationProvider = casAuthenticationProvider;
+ }
+
+
+ @Override
+ protected void configure(HttpSecurity http) throws Exception {
+ http.authorizeRequests().antMatchers( "/secured", "/login").authenticated()
+ .and()
+ .exceptionHandling().authenticationEntryPoint(authenticationEntryPoint())
+ .and()
+ .addFilterBefore(singleSignOutFilter, CasAuthenticationFilter.class)
+ .addFilterBefore(logoutFilter, LogoutFilter.class)
+ .csrf().ignoringAntMatchers("/exit/cas");
+ }
+
+ @Override
+ protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+ auth.authenticationProvider(casAuthenticationProvider);
+ }
+
+ @Bean
+ @Override
+ protected AuthenticationManager authenticationManager() throws Exception {
+ return new ProviderManager(Collections.singletonList(casAuthenticationProvider));
+ }
+
+ public AuthenticationEntryPoint authenticationEntryPoint() {
+ CasAuthenticationEntryPoint entryPoint = new CasAuthenticationEntryPoint();
+ entryPoint.setLoginUrl("https://localhost:8443/login");
+ entryPoint.setServiceProperties(serviceProperties);
+ return entryPoint;
+ }
+
+
+
+}
diff --git a/cas/cas-secured-app/src/main/java/com/baeldung/cassecuredapp/controllers/AuthController.java b/cas/cas-secured-app/src/main/java/com/baeldung/cassecuredapp/controllers/AuthController.java
index 2c88b74a83..16254c8cbd 100644
--- a/cas/cas-secured-app/src/main/java/com/baeldung/cassecuredapp/controllers/AuthController.java
+++ b/cas/cas-secured-app/src/main/java/com/baeldung/cassecuredapp/controllers/AuthController.java
@@ -1,7 +1,7 @@
package com.baeldung.cassecuredapp.controllers;
-import org.apache.log4j.LogManager;
-import org.apache.log4j.Logger;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.logout.CookieClearingLogoutHandler;
@@ -13,24 +13,27 @@ import org.springframework.web.bind.annotation.GetMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import static org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices.SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY;
+
@Controller
public class AuthController {
- private Logger logger = LogManager.getLogger(AuthController.class);
-
- @GetMapping("/logout")
- public String logout(
- HttpServletRequest request, HttpServletResponse response, SecurityContextLogoutHandler logoutHandler) {
- Authentication auth = SecurityContextHolder.getContext().getAuthentication();
- logoutHandler.logout(request, response, auth );
- new CookieClearingLogoutHandler(AbstractRememberMeServices.SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY).logout(request, response, auth);
- return "auth/logout";
- }
-
+ private Logger logger = LoggerFactory.getLogger(AuthController.class);
@GetMapping("/login")
public String login() {
+ logger.info("/login called");
return "redirect:/secured";
}
+
+ @GetMapping("/logout")
+ public String logout(HttpServletRequest request, HttpServletResponse response, SecurityContextLogoutHandler logoutHandler) {
+ Authentication auth = SecurityContextHolder.getContext().getAuthentication();
+ CookieClearingLogoutHandler cookieClearingLogoutHandler = new CookieClearingLogoutHandler(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY);
+ cookieClearingLogoutHandler.logout(request, response, auth);
+ logoutHandler.logout(request, response, auth);
+ return "auth/logout";
+ }
+
}
diff --git a/cas/cas-secured-app/src/main/java/com/baeldung/cassecuredapp/controllers/IndexController.java b/cas/cas-secured-app/src/main/java/com/baeldung/cassecuredapp/controllers/IndexController.java
index 75956cf493..d4800206d4 100644
--- a/cas/cas-secured-app/src/main/java/com/baeldung/cassecuredapp/controllers/IndexController.java
+++ b/cas/cas-secured-app/src/main/java/com/baeldung/cassecuredapp/controllers/IndexController.java
@@ -1,15 +1,19 @@
package com.baeldung.cassecuredapp.controllers;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-
@Controller
public class IndexController {
+ private Logger logger = LoggerFactory.getLogger(IndexController.class);
+
@GetMapping("/")
public String index() {
+ logger.info("Index controller called");
return "index";
}
+
}
diff --git a/cas/cas-secured-app/src/main/java/com/baeldung/cassecuredapp/controllers/SecuredController.java b/cas/cas-secured-app/src/main/java/com/baeldung/cassecuredapp/controllers/SecuredController.java
new file mode 100644
index 0000000000..0b3ab6199f
--- /dev/null
+++ b/cas/cas-secured-app/src/main/java/com/baeldung/cassecuredapp/controllers/SecuredController.java
@@ -0,0 +1,30 @@
+package com.baeldung.cassecuredapp.controllers;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.ModelMap;
+import org.springframework.web.bind.annotation.GetMapping;
+
+@Controller
+public class SecuredController {
+
+ private Logger logger = LoggerFactory.getLogger(SecuredController.class);
+
+ @GetMapping("/secured")
+ public String securedIndex(ModelMap modelMap) {
+
+ logger.info("/secured called");
+
+ Authentication auth = SecurityContextHolder.getContext()
+ .getAuthentication();
+
+ if(auth.getPrincipal() instanceof UserDetails)
+ modelMap.put("username", ((UserDetails) auth.getPrincipal()).getUsername());
+
+ return "secure/index";
+ }
+}
diff --git a/cas/cas-secured-app/src/main/java/com/baeldung/cassecuredapp/controllers/SecuredPageController.java b/cas/cas-secured-app/src/main/java/com/baeldung/cassecuredapp/controllers/SecuredPageController.java
deleted file mode 100644
index 9a872d1f40..0000000000
--- a/cas/cas-secured-app/src/main/java/com/baeldung/cassecuredapp/controllers/SecuredPageController.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.baeldung.cassecuredapp.controllers;
-
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.security.core.userdetails.UserDetails;
-import org.springframework.stereotype.Controller;
-import org.springframework.ui.ModelMap;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-
-@Controller
-@RequestMapping(value = "/secured")
-public class SecuredPageController {
-
- @GetMapping
- public String index(ModelMap modelMap) {
- Authentication auth = SecurityContextHolder.getContext().getAuthentication();
- if( auth != null && auth.getPrincipal() != null
- && auth.getPrincipal() instanceof UserDetails) {
- modelMap.put("username", ((UserDetails) auth.getPrincipal()).getUsername());
- }
- return "secure/index";
- }
-}
diff --git a/cas/cas-secured-app/src/main/resources/application.properties b/cas/cas-secured-app/src/main/resources/application.properties
index 99802c632f..f8789997d5 100644
--- a/cas/cas-secured-app/src/main/resources/application.properties
+++ b/cas/cas-secured-app/src/main/resources/application.properties
@@ -1 +1,2 @@
-server.port=9000
\ No newline at end of file
+server.port=8900
+spring.freemarker.suffix=.ftl
\ No newline at end of file
diff --git a/cas/cas-secured-app/src/test/java/com/baeldung/cassecuredapp/CasSecuredAppApplicationIntegrationTest.java b/cas/cas-secured-app/src/test/java/com/baeldung/cassecuredapp/CasSecuredApplicationIntegrationTest.java
similarity index 84%
rename from cas/cas-secured-app/src/test/java/com/baeldung/cassecuredapp/CasSecuredAppApplicationIntegrationTest.java
rename to cas/cas-secured-app/src/test/java/com/baeldung/cassecuredapp/CasSecuredApplicationIntegrationTest.java
index 2f2644e2ea..de13f6665d 100644
--- a/cas/cas-secured-app/src/test/java/com/baeldung/cassecuredapp/CasSecuredAppApplicationIntegrationTest.java
+++ b/cas/cas-secured-app/src/test/java/com/baeldung/cassecuredapp/CasSecuredApplicationIntegrationTest.java
@@ -7,7 +7,7 @@ import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
-public class CasSecuredAppApplicationIntegrationTest {
+public class CasSecuredApplicationIntegrationTest {
@Test
public void contextLoads() {
diff --git a/cas/cas-server/.factorypath b/cas/cas-server/.factorypath
deleted file mode 100644
index 006c761796..0000000000
--- a/cas/cas-server/.factorypath
+++ /dev/null
@@ -1,228 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/cas/cas-server/.gitignore b/cas/cas-server/.gitignore
old mode 100644
new mode 100755
index 5304519922..6121b5ea9d
--- a/cas/cas-server/.gitignore
+++ b/cas/cas-server/.gitignore
@@ -2,6 +2,8 @@
!/.project
.project
.settings
+.history
+.vscode
target/
.idea/
.DS_Store
@@ -9,6 +11,11 @@ target/
overlays/
.gradle/
build/
+log/
bin/
+*.war
*.iml
*.log
+tmp/
+./apache-tomcat
+apache-tomcat.zip
\ No newline at end of file
diff --git a/cas/cas-server/.mergify.yml b/cas/cas-server/.mergify.yml
new file mode 100644
index 0000000000..4fcbdbe4ac
--- /dev/null
+++ b/cas/cas-server/.mergify.yml
@@ -0,0 +1,32 @@
+#
+# Licensed to Apereo under one or more contributor license
+# agreements. See the NOTICE file distributed with this work
+# for additional information regarding copyright ownership.
+# Apereo licenses this file to you under the Apache License,
+# Version 2.0 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a
+# copy of the License at the following location:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+pull_request_rules:
+- name: automatic merge by dependabot
+ conditions:
+ - status-success=continuous-integration/travis-ci/pr
+ - status-success=WIP
+ - "#changes-requested-reviews-by=0"
+ - base=master
+ - label=dependencies
+ actions:
+ merge:
+ method: merge
+ strict: true
+ delete_head_branch:
\ No newline at end of file
diff --git a/cas/cas-server/.travis.yml b/cas/cas-server/.travis.yml
new file mode 100644
index 0000000000..8347dd1719
--- /dev/null
+++ b/cas/cas-server/.travis.yml
@@ -0,0 +1,62 @@
+language: java
+sudo: required
+dist: trusty
+services:
+ - docker
+branches:
+ only:
+ - master
+before_cache:
+ - rm -rf $HOME/.gradle/caches/5.*/
+ - rm -rf $HOME/.gradle/caches/4.*/
+ - rm -fr $HOME/.gradle/caches/*/plugin-resolution/
+ - find ~/.gradle/caches/ -name "*.lock" -type f -delete
+cache:
+ bundler: false
+ cargo: false
+ directories:
+ - $HOME/.m2
+ - $HOME/.npm/
+ - $HOME/.gradle/caches/
+ - $HOME/.gradle/wrapper/
+env:
+ global:
+ - JAVA_OPTS="-Xms512m -Xmx4048m -Xss128m -XX:ReservedCodeCacheSize=512m -XX:+UseG1GC -Xverify:none -server"
+ - GRADLE_OPTS="-Xms512m -Xmx1024m -Xss128m -XX:ReservedCodeCacheSize=512m -XX:+UseG1GC -Xverify:none -server"
+jdk:
+- openjdk11
+before_install:
+- echo -e "Configuring Gradle wrapper...\n"
+- mkdir -p ~/.gradle && echo "org.gradle.daemon=false" >> ~/.gradle/gradle.properties
+- chmod -R 777 ./gradlew
+- chmod -R 777 *.sh
+install: true
+stages:
+ - build
+ - validate
+ - docker
+jobs:
+ include:
+ - stage: build
+ script: ./gradlew clean build --stacktrace --no-daemon --refresh-dependencies -Dorg.gradle.internal.http.socketTimeout=600000 -Dorg.gradle.internal.http.connectionTimeout=600000
+ name: "Build CAS"
+ ############################################
+ - stage: validate
+ script: ./gradlew downloadShell
+ name: "Download CAS Shell"
+ - stage: validate
+ script: ./gradlew listTemplateViews
+ name: "List CAS Template Views"
+ - stage: validate
+ script: ./gradlew explodeWar
+ name: "Unzip CAS Web Application"
+ ############################################
+ - stage: docker
+ script: ./gradlew build jibDockerBuild --stacktrace --no-daemon --refresh-dependencies
+ name: "Build Docker Image via Jib"
+ - stage: docker
+ script: docker-compose build
+ name: "Build Docker Image via Docker Compose"
+ - stage: docker
+ script: ./docker-build.sh
+ name: "Build Docker Image"
\ No newline at end of file
diff --git a/cas/cas-server/Dockerfile b/cas/cas-server/Dockerfile
new file mode 100644
index 0000000000..b2f15ef4c3
--- /dev/null
+++ b/cas/cas-server/Dockerfile
@@ -0,0 +1,40 @@
+FROM adoptopenjdk/openjdk11:alpine-slim AS overlay
+
+RUN mkdir -p cas-overlay
+COPY ./src cas-overlay/src/
+COPY ./gradle/ cas-overlay/gradle/
+COPY ./gradlew ./settings.gradle ./build.gradle ./gradle.properties /cas-overlay/
+
+RUN mkdir -p ~/.gradle \
+ && echo "org.gradle.daemon=false" >> ~/.gradle/gradle.properties \
+ && echo "org.gradle.configureondemand=true" >> ~/.gradle/gradle.properties \
+ && cd cas-overlay \
+ && chmod 750 ./gradlew \
+ && ./gradlew --version;
+
+RUN cd cas-overlay \
+ && ./gradlew clean build --parallel;
+
+FROM adoptopenjdk/openjdk11:alpine-jre AS cas
+
+LABEL "Organization"="Apereo"
+LABEL "Description"="Apereo CAS"
+
+RUN cd / \
+ && mkdir -p /etc/cas/config \
+ && mkdir -p /etc/cas/services \
+ && mkdir -p /etc/cas/saml \
+ && mkdir -p cas-overlay;
+
+COPY etc/cas/ /etc/cas/
+COPY etc/cas/config/ /etc/cas/config/
+COPY etc/cas/services/ /etc/cas/services/
+COPY etc/cas/saml/ /etc/cas/saml/
+COPY --from=overlay cas-overlay/build/libs/cas.war cas-overlay/
+
+EXPOSE 8080 8443
+
+ENV PATH $PATH:$JAVA_HOME/bin:.
+
+WORKDIR cas-overlay
+ENTRYPOINT ["java", "-server", "-noverify", "-Xmx2048M", "-jar", "cas.war"]
diff --git a/cas/cas-server/README.md b/cas/cas-server/README.md
index 44cfa2246c..b224738732 100644
--- a/cas/cas-server/README.md
+++ b/cas/cas-server/README.md
@@ -1,105 +1,146 @@
-CAS Overlay Template
-============================
+CAS Overlay Template [](https://travis-ci.org/apereo/cas-overlay-template)
+=======================
-Generic CAS WAR overlay to exercise the latest versions of CAS. This overlay could be freely used as a starting template for local CAS war overlays. The CAS services management overlay is available [here](https://github.com/apereo/cas-services-management-overlay).
+Generic CAS WAR overlay to exercise the latest versions of CAS. This overlay could be freely used as a starting template for local CAS war overlays.
# Versions
-```xml
-5.3.x
+- CAS `6.1.x`
+- JDK `11`
+
+# Overview
+
+To build the project, use:
+
+```bash
+# Use --refresh-dependencies to force-update SNAPSHOT versions
+./gradlew[.bat] clean build
```
-# Requirements
-
-* JDK 1.8+
-
-# Configuration
-
-The `etc` directory contains the configuration files and directories that need to be copied to `/etc/cas/config`.
-
-# Build
-
To see what commands are available to the build script, run:
```bash
-./build.sh help
+./gradlew[.bat] tasks
```
-To package the final web application, run:
+To launch into the CAS command-line shell:
```bash
-./build.sh package
+./gradlew[.bat] downloadShell runShell
```
-To update `SNAPSHOT` versions run:
+To fetch and overlay a CAS resource or view, use:
```bash
-./build.sh package -U
+./gradlew[.bat] getResource -PresourceName=[resource-name]
```
+To list all available CAS views and templates:
+
+```bash
+./gradlew[.bat] listTemplateViews
+```
+
+To unzip and explode the CAS web application file and the internal resources jar:
+
+```bash
+./gradlew[.bat] explodeWar
+```
+
+# Configuration
+
+- The `etc` directory contains the configuration files and directories that need to be copied to `/etc/cas/config`.
+
+```bash
+./gradlew[.bat] copyCasConfiguration
+```
+
+- The specifics of the build are controlled using the `gradle.properties` file.
+
+## Adding Modules
+
+CAS modules may be specified under the `dependencies` block of the [Gradle build script](build.gradle):
+
+```gradle
+dependencies {
+ compile "org.apereo.cas:cas-server-some-module:${project.casVersion}"
+ ...
+}
+```
+
+To collect the list of all project modules and dependencies:
+
+```bash
+./gradlew[.bat] allDependencies
+```
+
+### Clear Gradle Cache
+
+If you need to, on Linux/Unix systems, you can delete all the existing artifacts (artifacts and metadata) Gradle has downloaded using:
+
+```bash
+# Only do this when absolutely necessary
+rm -rf $HOME/.gradle/caches/
+```
+
+Same strategy applies to Windows too, provided you switch `$HOME` to its equivalent in the above command.
+
# Deployment
-- Create a keystore file `thekeystore` under `/etc/cas`. Use the password `changeit` for both the keystore and the key/certificate entries.
+- Create a keystore file `thekeystore` under `/etc/cas`. Use the password `changeit` for both the keystore and the key/certificate entries. This can either be done using the JDK's `keytool` utility or via the following command:
+
+```bash
+./gradlew[.bat] createKeystore
+```
+
- Ensure the keystore is loaded up with keys and certificates of the server.
On a successful deployment via the following methods, CAS will be available at:
-* `http://cas.server.name:8080/cas`
* `https://cas.server.name:8443/cas`
## Executable WAR
-Run the CAS web application as an executable WAR.
+Run the CAS web application as an executable WAR:
```bash
-./build.sh run
+./gradlew[.bat] run
```
-## Spring Boot
-
-Run the CAS web application as an executable WAR via Spring Boot. This is most useful during development and testing.
+Debug the CAS web application as an executable WAR:
```bash
-./build.sh bootrun
+./gradlew[.bat] debug
```
-### Warning!
+Run the CAS web application as a *standalone* executable WAR:
-Be careful with this method of deployment. `bootRun` is not designed to work with already executable WAR artifacts such that CAS server web application. YMMV. Today, uses of this mode ONLY work when there is **NO OTHER** dependency added to the build script and the `cas-server-webapp` is the only present module. See [this issue](https://github.com/spring-projects/spring-boot/issues/8320) for more info.
-
-
-## Spring Boot App Server Selection
-
-There is an app.server property in the `pom.xml` that can be used to select a spring boot application server.
-It defaults to `-tomcat` but `-jetty` and `-undertow` are supported.
-
-It can also be set to an empty value (nothing) if you want to deploy CAS to an external application server of your choice.
-
-```xml
--tomcat
-```
-
-## Windows Build
-
-If you are building on windows, try `build.cmd` instead of `build.sh`. Arguments are similar but for usage, run:
-
-```
-build.cmd help
+```bash
+./gradlew[.bat] clean executable
```
## External
-Deploy resultant `target/cas.war` to a servlet container of choice.
+Deploy the binary web application file `cas.war` after a successful build to a servlet container of choice.
+## Docker
-## Command Line Shell
+The following strategies outline how to build and deploy CAS Docker images.
-Invokes the CAS Command Line Shell. For a list of commands either use no arguments or use `-h`. To enter the interactive shell use `-sh`.
+### Jib
+
+The overlay embraces the [Jib Gradle Plugin](https://github.com/GoogleContainerTools/jib) to provide easy-to-use out-of-the-box tooling for building CAS docker images. Jib is an open-source Java containerizer from Google that lets Java developers build containers using the tools they know. It is a container image builder that handles all the steps of packaging your application into a container image. It does not require you to write a Dockerfile or have Docker installed, and it is directly integrated into the overlay.
```bash
-./build.sh cli
+./gradlew build jibDockerBuild
```
-### Relevant Articles:
+### Dockerfile
-- [CAS SSO With Spring Security](https://www.baeldung.com/spring-security-cas-sso)
+You can also use the native Docker tooling and the provided `Dockerfile` to build and run CAS.
+
+```bash
+chmod +x *.sh
+./docker-build.sh
+./docker-run.sh
+```
diff --git a/cas/cas-server/build.cmd b/cas/cas-server/build.cmd
deleted file mode 100644
index 2cf9262afe..0000000000
--- a/cas/cas-server/build.cmd
+++ /dev/null
@@ -1,102 +0,0 @@
-@echo off
-
-@set JAVA_ARGS=-Xms500m -Xmx1g
-@set CAS_DIR=\etc\cas
-@set CONFIG_DIR=\etc\cas\config
-
-@rem Call this script with DNAME and CERT_SUBJ_ALT_NAMES already set to override
-@if "%DNAME%" == "" set DNAME=CN=cas.example.org,OU=Example,OU=Org,C=US
-@rem List other host names or ip addresses you want in your certificate, may help with host name verification,
-@rem if client apps make https connection for ticket validation and compare name in cert (include sub. alt. names)
-@rem to name used to access CAS
-@if "%CERT_SUBJ_ALT_NAMES%" == "" set CERT_SUBJ_ALT_NAMES=dns:example.org,dns:localhost,dns:%COMPUTERNAME%,ip:127.0.0.1
-
-@rem Check for mvn in path, use it if found, otherwise use maven wrapper
-@set MAVEN_CMD=mvn
-@where /q mvn
-@if %ERRORLEVEL% neq 0 set MAVEN_CMD=.\mvnw.bat
-
-@if "%1" == "" call:help
-@if "%1" == "copy" call:copy
-@if "%1" == "clean" call:clean %2 %3 %4
-@if "%1" == "package" call:package %2 %3 %4
-@if "%1" == "bootrun" call:bootrun %2 %3 %4
-@if "%1" == "debug" call:debug %2 %3 %4
-@if "%1" == "run" call:run %2 %3 %4
-@if "%1" == "runalone" call:runalone %2 %3 %4
-@if "%1" == "help" call:help
-@if "%1" == "gencert" call:gencert
-@if "%1" == "cli" call:runcli %2 %3 %4
-
-@rem function section starts here
-@goto:eof
-
-:copy
- @echo "Creating configuration directory under %CONFIG_DIR%"
- if not exist %CONFIG_DIR% mkdir %CONFIG_DIR%
-
- @echo "Copying configuration files from etc/cas to /etc/cas"
- xcopy /S /Y etc\cas\* \etc\cas
-@goto:eof
-
-:help
- @echo "Usage: build.bat [copy|clean|package|run|debug|bootrun|gencert|cli] [optional extra args for maven or cli]"
- @echo "To get started on a clean system, run "build.bat copy" and "build.bat gencert", then "build.bat run"
- @echo "Note that using the copy or gencert arguments will create and/or overwrite the %CAS_DIR% which is outside this project"
-@goto:eof
-
-:clean
- call %MAVEN_CMD% clean %1 %2 %3
- exit /B %ERRORLEVEL%
-@goto:eof
-
-:package
- call %MAVEN_CMD% clean package -T 5 %1 %2 %3
- exit /B %ERRORLEVEL%
-@goto:eof
-
-:bootrun
- call %MAVEN_CMD% clean package spring-boot:run -T 5 %1 %2 %3
- exit /B %ERRORLEVEL%
-@goto:eof
-
-:debug
- call:package %1 %2 %3 & java %JAVA_ARGS% -Xdebug -Xrunjdwp:transport=dt_socket,address=5000,server=y,suspend=n -jar target/cas.war
-@goto:eof
-
-:run
- call:package %1 %2 %3 & java %JAVA_ARGS% -jar target/cas.war
-@goto:eof
-
-:runalone
- call:package %1 %2 %3 & target/cas.war
-@goto:eof
-
-:gencert
- where /q keytool
- if ERRORLEVEL 1 (
- @echo Java keytool.exe not found in path.
- exit /b 1
- ) else (
- if not exist %CAS_DIR% mkdir %CAS_DIR%
- @echo on
- @echo Generating self-signed SSL cert for %DNAME% in %CAS_DIR%\thekeystore
- keytool -genkeypair -alias cas -keyalg RSA -keypass changeit -storepass changeit -keystore %CAS_DIR%\thekeystore -dname %DNAME% -ext SAN=%CERT_SUBJ_ALT_NAMES%
- @echo Exporting cert for use in trust store (used by cas clients)
- keytool -exportcert -alias cas -storepass changeit -keystore %CAS_DIR%\thekeystore -file %CAS_DIR%\cas.cer
- )
-@goto:eof
-
-:runcli
- for /f %%i in ('call %MAVEN_CMD% -q --non-recursive "-Dexec.executable=cmd" "-Dexec.args=/C echo ${cas.version}" "org.codehaus.mojo:exec-maven-plugin:1.3.1:exec"') do set CAS_VERSION=%%i
- @set CAS_VERSION=%CAS_VERSION: =%
- @set DOWNLOAD_DIR=target
- @set COMMAND_FILE=cas-server-support-shell-%CAS_VERSION%.jar
- @if not exist %DOWNLOAD_DIR% mkdir %DOWNLOAD_DIR%
- @if not exist %DOWNLOAD_DIR%\%COMMAND_FILE% (
- @call mvn org.apache.maven.plugins:maven-dependency-plugin:3.0.2:get -DgroupId=org.apereo.cas -DartifactId=cas-server-support-shell -Dversion=%CAS_VERSION% -Dpackaging=jar -DartifactItem.outputDirectory=%DOWNLOAD_DIR% -DartifactItem.destFileName=%COMMAND_FILE% -DremoteRepositories=central::default::http://repo1.maven.apache.org/maven2,snapshots::::https://oss.sonatype.org/content/repositories/snapshots -Dtransitive=false
- @call mvn org.apache.maven.plugins:maven-dependency-plugin:3.0.2:copy -Dmdep.useBaseVersion=true -Dartifact=org.apereo.cas:cas-server-support-shell:%CAS_VERSION%:jar -DoutputDirectory=%DOWNLOAD_DIR%
- )
- @call java %JAVA_ARGS% -jar %DOWNLOAD_DIR%\%COMMAND_FILE% %1 %2 %3
-
-@goto:eof
\ No newline at end of file
diff --git a/cas/cas-server/build.gradle b/cas/cas-server/build.gradle
new file mode 100644
index 0000000000..41381e2d8f
--- /dev/null
+++ b/cas/cas-server/build.gradle
@@ -0,0 +1,106 @@
+buildscript {
+ repositories {
+ mavenLocal()
+ mavenCentral()
+ jcenter()
+ maven { url "https://repo.spring.io/libs-milestone" }
+ maven { url "https://repo.spring.io/libs-snapshot" }
+ maven { url "https://plugins.gradle.org/m2/" }
+ }
+ dependencies {
+ classpath "de.undercouch:gradle-download-task:${project.gradleDownloadTaskVersion}"
+ classpath "org.springframework.boot:spring-boot-gradle-plugin:${project.springBootVersion}"
+ classpath "gradle.plugin.com.google.cloud.tools:jib-gradle-plugin:${project.jibVersion}"
+ classpath "io.freefair.gradle:maven-plugin:${project.gradleMavenPluginVersion}"
+ }
+}
+
+repositories {
+ mavenLocal()
+ mavenCentral()
+ jcenter()
+ maven { url "https://oss.sonatype.org/content/repositories/snapshots" }
+ maven { url "https://build.shibboleth.net/nexus/content/repositories/releases/" }
+ maven { url "https://repo.spring.io/milestone/" }
+ maven { url "https://repo.spring.io/snapshot/" }
+ maven { url "https://oss.jfrog.org/artifactory/oss-snapshot-local" }
+}
+
+def casServerVersion = project.'cas.version'
+def casWebApplicationBinaryName = "cas.war"
+
+project.ext."casServerVersion" = casServerVersion
+project.ext."casWebApplicationBinaryName" = casWebApplicationBinaryName
+
+apply plugin: "io.freefair.war-overlay"
+apply from: rootProject.file("gradle/tasks.gradle")
+
+apply plugin: "war"
+apply plugin: "eclipse"
+apply plugin: "idea"
+
+apply from: rootProject.file("gradle/springboot.gradle")
+apply from: rootProject.file("gradle/dockerjib.gradle")
+
+dependencies {
+ // Other CAS dependencies/modules may be listed here...
+ compile "org.apereo.cas:cas-server-support-json-service-registry:${casServerVersion}"
+ compile "org.apereo.cas:cas-server-support-jdbc:${casServerVersion}"
+}
+
+tasks.findByName("jibDockerBuild")
+ .dependsOn(copyWebAppIntoJib, copyConfigIntoJib)
+ .finalizedBy(deleteWebAppFromJib)
+
+tasks.findByName("jib")
+ .dependsOn(copyWebAppIntoJib, copyConfigIntoJib)
+ .finalizedBy(deleteWebAppFromJib)
+
+configurations.all {
+ resolutionStrategy {
+ cacheChangingModulesFor 0, "seconds"
+ cacheDynamicVersionsFor 0, "seconds"
+
+ preferProjectModules()
+
+ def failIfConflict = project.hasProperty("failOnVersionConflict") && Boolean.valueOf(project.getProperty("failOnVersionConflict"))
+ if (failIfConflict) {
+ failOnVersionConflict()
+ }
+ }
+}
+
+eclipse {
+ classpath {
+ downloadSources = true
+ downloadJavadoc = true
+ }
+}
+
+idea {
+ module {
+ downloadJavadoc = true
+ downloadSources = true
+ }
+}
+
+bootWar {
+ entryCompression = ZipEntryCompression.STORED
+ overlays {
+ // https://docs.freefair.io/gradle-plugins/current/reference/#_io_freefair_war_overlay
+ // Note: The "excludes" property is only for files in the war dependency.
+ // If a jar is excluded from the war, it could be brought back into the final war as a dependency
+ // of non-war dependencies. Those should be excluded via normal gradle dependency exclusions.
+ cas {
+ from "org.apereo.cas:cas-server-webapp${project.appServer}:${casServerVersion}@war"
+ provided = false
+ //excludes = ["WEB-INF/lib/somejar-1.0*"]
+ }
+ }
+}
+
+
+wrapper {
+ distributionType = Wrapper.DistributionType.BIN
+ gradleVersion = "${project.gradleVersion}"
+}
diff --git a/cas/cas-server/build.sh b/cas/cas-server/build.sh
deleted file mode 100644
index 4d80aa2593..0000000000
--- a/cas/cas-server/build.sh
+++ /dev/null
@@ -1,189 +0,0 @@
-#!/bin/bash
-
-
-function copy() {
- echo -e "Creating configuration directory under /etc/cas"
- mkdir -p /etc/cas/config
-
- echo -e "Copying configuration files from etc/cas to /etc/cas"
- cp -rfv etc/cas/* /etc/cas
-}
-
-function help() {
- echo "Usage: build.sh [copy|clean|package|run|debug|bootrun|gencert]"
- echo " copy: Copy config from ./etc/cas/config to /etc/cas/config"
- echo " clean: Clean Maven build directory"
- echo " package: Clean and build CAS war"
- echo " run: Build and run cas.war via Java (i.e. java -jar target/cas.war)"
- echo " runalone: Build and run cas.war on its own as a standalone executable (target/cas.war)"
- echo " debug: Run CAS.war and listen for Java debugger on port 5000"
- echo " bootrun: Run with maven spring boot plugin"
- echo " listviews: List all CAS views that ship with the web application and can be customized in the overlay"
- echo " getview: Ask for a view name to be included in the overlay for customizations"
- echo " gencert: Create keystore with SSL certificate in location where CAS looks by default"
- echo " cli: Run the CAS command line shell and pass commands"
-}
-
-function clean() {
- shift
- ./mvnw clean "$@"
-}
-
-function package() {
- shift
- ./mvnw clean package -T 5 "$@"
- # copy
-}
-
-function bootrun() {
- shift
- ./mvnw clean package spring-boot:run -P bootiful -T 5 "$@"
-}
-
-function debug() {
- package && java -Xdebug -Xrunjdwp:transport=dt_socket,address=5000,server=y,suspend=n -jar target/cas.war
-}
-
-function run() {
- package && java -jar target/cas.war
-}
-
-function runalone() {
- shift
- ./mvnw clean package -P default,exec "$@"
- chmod +x target/cas.war
- target/cas.war
-}
-
-function listviews() {
- shift
- explodeapp
- find $PWD/target/cas -type f -name "*.html" | xargs -n 1 basename | sort | more
-}
-
-function explodeapp() {
- if [ ! -d $PWD/target/cas ];then
- echo "Building the CAS web application and exploding the final war file..."
- ./mvnw clean package war:exploded "$@"
- fi
- echo "Exploded the CAS web application file."
-}
-
-function getview() {
- shift
- explodeapp
- echo "Searching for view name $@..."
- results=`find $PWD/target/cas -type f -name "*.html" | grep -i "$@"`
- echo -e "Found view(s): \n$results"
- count=`wc -w <<< "$results"`
- if [ "$count" -eq 1 ];then
- # echo "Found view $results to include in the overlay"
- firststring="target/cas/WEB-INF/classes"
- secondstring="src/main/resources"
- overlayfile=`echo "${results/$firststring/$secondstring}"`
- overlaypath=`dirname "${overlayfile}"`
- # echo "Overlay file is $overlayfile to be created at $overlaypath"
- mkdir -p $overlaypath
- cp $results $overlaypath
- echo "Created view at $overlayfile"
- ls $overlayfile
- else
- echo "More than one view file is found. Narrow down the search query..."
- fi
-}
-
-
-function gencert() {
- if [[ ! -d /etc/cas ]] ; then
- copy
- fi
- which keytool
- if [[ $? -ne 0 ]] ; then
- echo Error: Java JDK \'keytool\' is not installed or is not in the path
- exit 1
- fi
- # override DNAME and CERT_SUBJ_ALT_NAMES before calling or use dummy values
- DNAME="${DNAME:-CN=cas.example.org,OU=Example,OU=Org,C=US}"
- CERT_SUBJ_ALT_NAMES="${CERT_SUBJ_ALT_NAMES:-dns:example.org,dns:localhost,ip:127.0.0.1}"
- echo "Generating keystore for CAS with DN ${DNAME}"
- keytool -genkeypair -alias cas -keyalg RSA -keypass changeit -storepass changeit -keystore /etc/cas/thekeystore -dname ${DNAME} -ext SAN=${CERT_SUBJ_ALT_NAMES}
- keytool -exportcert -alias cas -storepass changeit -keystore /etc/cas/thekeystore -file /etc/cas/cas.cer
-}
-
-function cli() {
-
- CAS_VERSION=$(./mvnw -q -Dexec.executable="echo" -Dexec.args='${cas.version}' --non-recursive org.codehaus.mojo:exec-maven-plugin:1.3.1:exec 2>/dev/null)
- # echo "CAS version: $CAS_VERSION"
- JAR_FILE_NAME="cas-server-support-shell-${CAS_VERSION}.jar"
- # echo "JAR name: $JAR_FILE_NAME"
- JAR_PATH="org/apereo/cas/cas-server-support-shell/${CAS_VERSION}/${JAR_FILE_NAME}"
- # echo "JAR path: $JAR_PATH"
-
- JAR_FILE_LOCAL="$HOME/.m2/repository/$JAR_PATH";
- # echo "Local JAR file path: $JAR_FILE_LOCAL";
- if [ -f "$JAR_FILE_LOCAL" ]; then
- # echo "Using JAR file locally at $JAR_FILE_LOCAL"
- java -jar $JAR_FILE_LOCAL "$@"
- exit 0;
- fi
-
- DOWNLOAD_DIR=./target
- COMMAND_FILE="${DOWNLOAD_DIR}/${JAR_FILE_NAME}"
- if [ ! -f "$COMMAND_FILE" ]; then
- mkdir -p $DOWNLOAD_DIR
- ./mvnw org.apache.maven.plugins:maven-dependency-plugin:3.0.2:get -DgroupId=org.apereo.cas -DartifactId=cas-server-support-shell -Dversion=$CAS_VERSION -Dpackaging=jar -DartifactItem.outputDirectory=$DOWNLOAD_DIR -DremoteRepositories=central::default::http://repo1.maven.apache.org/maven2,snapshots::::https://oss.sonatype.org/content/repositories/snapshots -Dtransitive=false
- ./mvnw org.apache.maven.plugins:maven-dependency-plugin:3.0.2:copy -Dmdep.useBaseVersion=true -Dartifact=org.apereo.cas:cas-server-support-shell:$CAS_VERSION:jar -DoutputDirectory=$DOWNLOAD_DIR
- fi
- java -jar $COMMAND_FILE "$@"
- exit 0;
-
-}
-
-if [ $# -eq 0 ]; then
- echo -e "No commands provided. Defaulting to [run]\n"
- run
- exit 0
-fi
-
-case "$1" in
-"copy")
- copy
- ;;
-"clean")
- shift
- clean "$@"
- ;;
-"package")
- shift
- package "$@"
- ;;
-"bootrun")
- shift
- bootrun "$@"
- ;;
-"debug")
- debug "$@"
- ;;
-"run")
- run "$@"
- ;;
-"runalone")
- runalone "$@"
- ;;
-"listviews")
- listviews "$@"
- ;;
-"gencert")
- gencert "$@"
- ;;
-"getview")
- getview "$@"
- ;;
-"cli")
- shift
- cli "$@"
- ;;
-*)
- help
- ;;
-esac
diff --git a/cas/cas-server/docker-build.sh b/cas/cas-server/docker-build.sh
new file mode 100755
index 0000000000..8f2c2776bf
--- /dev/null
+++ b/cas/cas-server/docker-build.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+image_tag=(`cat gradle.properties | grep "cas.version" | cut -d= -f2`)
+
+echo "Building CAS docker image tagged as [$image_tag]"
+# read -p "Press [Enter] to continue..." any_key;
+
+docker build --tag="org.apereo.cas/cas:$image_tag" . \
+ && echo "Built CAS image successfully tagged as org.apereo.cas/cas:$image_tag" \
+ && docker images "org.apereo.cas/cas:$image_tag"
\ No newline at end of file
diff --git a/cas/cas-server/docker-compose.yml b/cas/cas-server/docker-compose.yml
new file mode 100644
index 0000000000..8f2e6ca7c9
--- /dev/null
+++ b/cas/cas-server/docker-compose.yml
@@ -0,0 +1,7 @@
+version: '3'
+services:
+ cas:
+ build: .
+ ports:
+ - "8443:8443"
+ - "8080:8080"
\ No newline at end of file
diff --git a/cas/cas-server/docker-push.sh b/cas/cas-server/docker-push.sh
new file mode 100755
index 0000000000..e04b107212
--- /dev/null
+++ b/cas/cas-server/docker-push.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+read -p "Docker username: " docker_user
+read -s -p "Docker password: " docker_psw
+
+echo "$docker_psw" | docker login --username "$docker_user" --password-stdin
+
+image_tag=(`cat gradle.properties | grep "cas.version" | cut -d= -f2`)
+
+echo "Pushing CAS docker image tagged as $image_tag to org.apereo.cas/cas..."
+docker push org.apereo.cas/cas:"$image_tag" \
+ && echo "Pushed org.apereo.cas/cas:$image_tag successfully.";
\ No newline at end of file
diff --git a/cas/cas-server/docker-run.sh b/cas/cas-server/docker-run.sh
new file mode 100755
index 0000000000..f8627859f2
--- /dev/null
+++ b/cas/cas-server/docker-run.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+docker stop cas > /dev/null 2>&1
+docker rm cas > /dev/null 2>&1
+image_tag=(`cat gradle.properties | grep "cas.version" | cut -d= -f2`)
+docker run -d -p 8080:8080 -p 8443:8443 --name="cas" org.apereo.cas/cas:"${image_tag}"
+docker logs -f cas
\ No newline at end of file
diff --git a/cas/cas-server/etc/cas/config/application.yml b/cas/cas-server/etc/cas/config/application.yml
deleted file mode 100644
index be1f7c3edd..0000000000
--- a/cas/cas-server/etc/cas/config/application.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-info:
- description: CAS Configuration
\ No newline at end of file
diff --git a/cas/cas-server/etc/cas/config/cas.properties b/cas/cas-server/etc/cas/config/cas.properties
index 47a1477308..a3be0e1388 100644
--- a/cas/cas-server/etc/cas/config/cas.properties
+++ b/cas/cas-server/etc/cas/config/cas.properties
@@ -1,7 +1,6 @@
-cas.server.name: https://cas.example.org:8443
-cas.server.prefix: https://cas.example.org:8443/cas
-
-cas.adminPagesSecurity.ip=127\.0\.0\.1
+cas.server.name=https://cas.example.org:8443
+cas.server.prefix=${cas.server.name}/cas
logging.config: file:/etc/cas/config/log4j2.xml
-# cas.serviceRegistry.config.location: classpath:/services
+
+# cas.authn.accept.users=
diff --git a/cas/cas-server/etc/cas/config/log4j2.xml b/cas/cas-server/etc/cas/config/log4j2.xml
index e688cc0350..685dfab245 100644
--- a/cas/cas-server/etc/cas/config/log4j2.xml
+++ b/cas/cas-server/etc/cas/config/log4j2.xml
@@ -2,20 +2,26 @@
-
- .
-
- warn
+ /var/log
+
+ info
+ warn
+ info
+ warn
+ debug
+ warn
+ warn
+ warn
+ warn
+ warn
+ warn
-
+
-
+
@@ -23,8 +29,8 @@
-
+
@@ -33,16 +39,6 @@
-
-
-
-
-
-
-
-
-
@@ -52,52 +48,58 @@
-
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cas/cas-server/etc/cas/saml/.gitkeep b/cas/cas-server/etc/cas/saml/.gitkeep
new file mode 100644
index 0000000000..882c99944d
--- /dev/null
+++ b/cas/cas-server/etc/cas/saml/.gitkeep
@@ -0,0 +1 @@
+This directory is references in the Dockerfile so it needs to be here.
\ No newline at end of file
diff --git a/cas/cas-server/etc/cas/services/.donotdel b/cas/cas-server/etc/cas/services/.donotdel
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/cas/cas-server/etc/cas/thekeystore b/cas/cas-server/etc/cas/thekeystore
new file mode 100644
index 0000000000000000000000000000000000000000..78f49baf743bc53e74cb67746992be258229c310
GIT binary patch
literal 2266
zcmcgtc{J1w7oOkD7#YUW2w6i>BlG^ol6P!l$THbwi=vqO}
zmYOk062e%@YtIrw=n$_u-*?XY$M^U5$35ph&%O7Yd!BpGy}Ms`zd|4o=)M8J4R(p_
zyYExV1$Fib4gjRWe}cRSqyhqf0~n|P0B}IyRQMbrXw&-UkX;%=H~+&uQHb3Frx62$
z_ZK7qS)+$zucd0azsOV;vTvu0vLqElCvV!Bz-nJ9z0&irkt8K}>
zJrJ0~8>Cg57A~TFKxJviS1W$}L~4=(L-R7?3at^Tsq;scd>n;pKWwh!gk
zHC$)eb@&cVlM2zX_W@HEh9*x)v
zgKta)@yyS69GS8R`>Z(0YN)IEzQVZ^iDlFD;~52}`o5~x{X!0;0pT&YEiSI}8E*;U
z=hN#w;gi$FL-$)IGePw7*<
zmNTt?+v_`pF(tYoc73CozG)E;p5DJDwJ}sl^L{c-AVfM3FdF-nd0(@{#`N_#H$=jLe(4bHNWu@5aLK?nlJknSS
zu;;hSYCw!P&g=g0h>DA|=talkLx%R|qAzD47Oqr8`8qpGzj2xSa^Qn(uAdbwMsdNq
z8RKuxv6h}(9Kj}IsMQqz}-*N4iT_2YBLotQ?S`s7Ck
z$~3kH>KB-NiI17cT&J_|b_E^F^X1J*BHCxAoz6)-HlC&Ad9Wr*vQ?52Z>g=@Bn@VI
zR=b)L-5MX)P;KD2`NI*Kuu{44*b+r-aJt`rY`43SMqajA)YU6i{_b1TT5mgbXe5!Gu1wODRyDKyKPR}CzVMcuGh@|Q-ek5
zA4QaYQ4<$hmyFrb>5MYPjq~pBG_(84xfv&W`g(l`T!E`E`qOjU8N($aQ7>Z~h3rhy
zpWJ8qC6ChX34iDPbl#?W`ZPMhG;+`FrCUS8WLuDxArD@CtVPGHIjy;T8Y7}QCHHFS
z;Nu`}=~i#s;a*Ag*rw|B=B413OsXDxt7wtYjUyQ5mO`v$S9DvU=_q<2v_3GogQOC}
zHjB)rH#74^nnj62H=8P;%>z+?`}cV#bLh$L74>df7vk>Xg?^Aq$VJy41tWm3;&*}u+!
zHva7yjdS>;&Tb92p?=E*A6BMuectg9sHt4CbqaaA=GeAaox#W5Dj$-j-R&B_s9;X{
z0#1V`H=3~6(uXD|6R12RJ7f)Q5j?E@L_|X8(haAnVcs5Z?K&ji`j;2%^MX^gq
zN*viE94`y+7+A#X%+iX=R?S=%@}M%JUSXjHiY^7(IiHQ(+E3T5hbXmuAgjVinXE|h
z%5Mvqd1O6#L8%)TlscV;(YM`>UclguYfrdmeH;}?iWB+p`zmtSV^u*s1Om$dsjyU#
z3JuPOK>;Wf?p*0c22ltuOtew-CJF$!IUt}1jvM4cz--_MG}Pwof58DXl<0ut-@m2%
z5l%Fxp~qE<>kU5~-+uW%gG3{2yge@Yc;k3LdvapIupF9buQy}W$L!NIOB
zSpVO7SZ`N9P*NC$`x8_F@i-i)qO9Z~j8ejZI8f<7@c-Eg6_EM25c_WeMg{mFAQeDD
zsQ>`EV_RHzx&jx_^cq|Zo*Uu0^uq(A+_E@k`j$#e6S&rY_(#^dxusOEK69>M9?MpY)kf|5u@rMWaLTZzZfK#}jVIyAih7z9a+uP;{Dy@L*x%FsVpunNTDoZ9;=G
z{@!%%t=+EC*UkW*#j5U{;A!G7+r4Oh(le*nVg3nK2{TF78IqV$ms7|rn{<-wwG`Ka
z!T<H82FI)&Nn30Q)ncWKYf3nUB_0+rRnkXY-@Nbd#
zw{2f!0OIJNo^3StQ#U7l<9+9DKVZxlEaJ%$!wJ6
z6y$N8ju9&GIoHjG{`%BfHLvFEghR}L(EF*~33ki6J^q26u&QY?_ulsTmLA~Z?EJ_K
z#`Cbk_~lkrrplSv7MNqqO;V5i7h)I!ubXvUEq!K7elbcRf@d1WB|+%te4Vg!V~%mD
zKu{0Q3~v%(o|O36HCAaN%H{v`*!faCu~=huy*1>n1`V@gq#)KN;|&`^$Sln(Arrays.asList("-server -noverify -Xmx2048M -XX:+TieredCompilation -XX:TieredStopAtLevel=1".split(" ")))
+ if (project.hasProperty('args')) {
+ casRunArgs.addAll(project.args.split('\\s+'))
+ }
+ javaexec {
+ main = "-jar"
+ jvmArgs = casRunArgs
+ args = ["build/libs/${casWebApplicationBinaryName}"]
+ logger.info "Started ${commandLine}"
+ }
+ }
+}
+
+task setExecutable(group: "build", description: "Configure the project to run in executable mode") {
+ doFirst {
+ project.setProperty("executable", "true")
+ logger.info "Configuring the project as executable"
+ }
+}
+
+task executable(type:Exec, group: "build", description: "Run the CAS web application in standalone executable mode") {
+ dependsOn setExecutable, 'build'
+ doFirst {
+ workingDir "."
+ if (!Os.isFamily(Os.FAMILY_WINDOWS)) {
+ commandLine "chmod", "+x", bootWar.archivePath
+ }
+ logger.info "Running ${bootWar.archivePath}"
+ commandLine bootWar.archivePath
+ }
+}
+
+task debug(group: "build", description: "Debug the CAS web application in embedded mode on port 5005") {
+ dependsOn 'build'
+ doLast {
+ logger.info "Debugging process is started in a suspended state, listening on port 5005."
+ def casArgs = Arrays.asList("-Xmx2048M".split(" "))
+ javaexec {
+ main = "-jar"
+ jvmArgs = casArgs
+ debug = true
+ args = ["build/libs/${casWebApplicationBinaryName}"]
+ logger.info "Started ${commandLine}"
+ }
+ }
+}
+
+task downloadShell(group: "shell", description: "Download CAS shell jar from snapshot or release maven repo") {
+ doFirst {
+ mkdir "${project.shellDir}"
+ }
+ doLast {
+ def downloadFile
+ if (isRunningCasServerSnapshot(casServerVersion)) {
+ def snapshotDir = "https://oss.sonatype.org/content/repositories/snapshots/org/apereo/cas/cas-server-support-shell/${casServerVersion}/"
+ def files = new ApacheURLLister().listFiles(new URL(snapshotDir))
+ files = files.sort{it.path}
+ files.each {
+ if (it.path.endsWith(".jar")) {
+ downloadFile = it
+ }
+ }
+ } else {
+ downloadFile = "https://repo1.maven.org/maven2/org/apereo/cas/cas-server-support-shell/${casServerVersion}/cas-server-support-shell-${casServerVersion}.jar"
+ }
+ logger.info "Downloading file: ${downloadFile}"
+ download {
+ src downloadFile
+ dest new File("${project.shellDir}", "cas-server-support-shell-${casServerVersion}.jar")
+ overwrite false
+ }
+ }
+}
+
+task runShell(group: "shell", description: "Run the CAS shell") {
+ dependsOn downloadShell
+ doLast {
+ println "Run the following command to launch the shell:\n\tjava -jar ${project.shellDir}/cas-server-support-shell-${casServerVersion}.jar"
+ }
+}
+
+task debugShell(group: "shell", description: "Run the CAS shell with debug options, wait for debugger on port 5005") {
+ dependsOn downloadShell
+ doLast {
+ println """
+ Run the following command to launch the shell:\n\t
+ java -Xrunjdwp:transport=dt_socket,address=5000,server=y,suspend=y -jar ${project.shellDir}/cas-server-support-shell-${casServerVersion}.jar
+ """
+ }
+}
+
+task showConfiguration(group: "build", description: "Show configurations for each dependency, etc") {
+ doLast() {
+ def cfg = project.hasProperty("configuration") ? project.property("configuration") : "compile"
+ configurations.getByName(cfg).each { println it }
+ }
+}
+
+task allDependenciesInsight(group: "build", type: DependencyInsightReportTask, description: "Produce insight information for all dependencies") {}
+
+task allDependencies(group: "build", type: DependencyReportTask, description: "Display a graph of all project dependencies") {}
+
+task casVersion (group: "build", description: "Display the current CAS version") {
+ doFirst {
+ def verbose = project.hasProperty("verbose") && Boolean.valueOf(project.getProperty("verbose"))
+ if (verbose) {
+ def out = services.get(StyledTextOutputFactory).create("CAS")
+ println "******************************************************************"
+ out.withStyle(Style.Info).println "Apereo CAS $casServerVersion"
+ out.withStyle(Style.Description).println "Enterprise Single SignOn for all earthlings and beyond"
+ out.withStyle(Style.SuccessHeader).println "- GitHub: "
+ out.withStyle(Style.Success).println "https://github.com/apereo/cas"
+ out.withStyle(Style.SuccessHeader).println "- Docs: "
+ out.withStyle(Style.Success).println "https://apereo.github.io/cas"
+ out.withStyle(Style.SuccessHeader).println "- Blog: "
+ out.withStyle(Style.Success).println "https://apereo.github.io"
+ println "******************************************************************"
+ } else {
+ println casServerVersion
+ }
+ }
+}
+
+task createKeystore(group: "build", description: "Create CAS keystore") {
+ doFirst {
+ mkdir "/etc/cas"
+
+ def keystorePath = "/etc/cas/thekeystore"
+
+ def dn = "CN=cas.example.org,OU=Example,OU=Org,C=US"
+ if (project.hasProperty("certificateDn")) {
+ dn = project.getProperty("certificateDn")
+ }
+ def subjectAltName = "dns:example.org,dns:localhost,ip:127.0.0.1"
+ if (project.hasProperty("certificateSubAltName")) {
+ subjectAltName = project.getProperty("certificateSubAltName")
+ }
+ // this will fail if thekeystore exists and has cert with cas alias already (so delete if you want to recreate)
+ logger.info "Generating keystore for CAS with DN ${dn}"
+ exec {
+ workingDir "."
+ commandLine "keytool", "-genkeypair", "-alias", "cas",
+ "-keyalg", "RSA",
+ "-keypass", "changeit", "-storepass", "changeit",
+ "-keystore", keystorePath,
+ "-dname", dn, "-ext", "SAN=${subjectAltName}"
+ }
+ logger.info "Exporting cert from keystore..."
+ exec {
+ workingDir "."
+ commandLine "keytool", "-exportcert", "-alias", "cas",
+ "-storepass", "changeit", "-keystore", keystorePath,
+ "-file", "/etc/cas/cas.cer"
+ }
+ logger.info "Import /etc/cas/cas.cer into your Java truststore (JAVA_HOME/lib/security/cacerts)"
+ }
+}
+
+task listTemplateViews (group: "build", description: "List all CAS views") {
+ dependsOn explodeWar
+
+ doFirst {
+ fileTree(explodedResourcesDir).matching {
+ include "**/*.html"
+ }
+ .collect { it.name }
+ .toSorted()
+ .each { println it }
+ }
+}
+
+task getResource(group: "build", description: "Fetch a CAS resource and move it into the overlay") {
+ dependsOn explodeWar
+
+ doFirst {
+ def resourceName = project.getProperty("resourceName")
+
+ def results = fileTree(explodedResourcesDir).matching {
+ include "**/${resourceName}.*"
+ }
+ if (results.isEmpty()) {
+ println "No resources could be found matching ${resourceName}"
+ return
+ }
+ if (results.size() > 1) {
+ println "Multiple resources found matching ${resourceName}: ${results}"
+ return
+ }
+
+ def fromFile = explodedResourcesDir
+ def resourcesDir = "src/main/resources"
+ mkdir resourcesDir
+
+ def resourceFile = results[0].canonicalPath
+ def toResourceFile = resourceFile.replace(fromFile, resourcesDir)
+
+ def parent = file(toResourceFile).getParent()
+ mkdir parent
+
+ Files.copy(Paths.get(resourceFile), Paths.get(toResourceFile), StandardCopyOption.REPLACE_EXISTING)
+ println "Copied file ${resourceFile} to ${toResourceFile}"
+ }
+}
+
+def isRunningCasServerSnapshot(casServerVersion) {
+ return "${casServerVersion}".contains("-SNAPSHOT")
+}
\ No newline at end of file
diff --git a/cas/cas-server/gradle/wrapper/gradle-wrapper.properties b/cas/cas-server/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000000..f04d6a20ae
--- /dev/null
+++ b/cas/cas-server/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.3-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/cas/cas-server/gradlew b/cas/cas-server/gradlew
new file mode 100755
index 0000000000..83f2acfdc3
--- /dev/null
+++ b/cas/cas-server/gradlew
@@ -0,0 +1,188 @@
+#!/usr/bin/env sh
+
+#
+# Copyright 2015 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/cas/cas-server/gradlew.bat b/cas/cas-server/gradlew.bat
new file mode 100644
index 0000000000..24467a141f
--- /dev/null
+++ b/cas/cas-server/gradlew.bat
@@ -0,0 +1,100 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/cas/cas-server/maven/maven-wrapper.jar b/cas/cas-server/maven/maven-wrapper.jar
deleted file mode 100644
index 18ba302c65c4f71f57e0daa0ea1b59cb85759b5c..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 71910
zcmb@t1#nzTk}fR97BgAQ%wRDyGoytqwpg+xics%_`HC{i2v=+-@jl#e&xheh3KW^#Tga8TMq8G2zD=z{|F1Wei1
zP_t5ZxFL@rk09iG>Nb7qRU%rtJHVct@57ZND9C>p2Li(Pmp(vz7-wP!{7>`$tHdAX
z{~_UM2{d!GbF#Df>TGFe>+~-)aQ`nFKqD73+kc@)@-Ox5ZN8dY{>yf0{-5++9gXbm
z%^d&1j;Ftj3DU=N{?o7j&S>WUD*Q2841XCdhQB?A;lK9buWkP^!T!?rzkl4{yF~xD
zM(F=+V}v
z%l|YG=5O;m0fyU-_(O&8<6{4~{=3=xr=|blkN+?M=wj@Wsx~+00QzIb>H^QLz*e
z$q@i!j}Z3g0JwL0utz9UQ&e_P+ynd1nEJC#*YlE;1W*tVG;k0Q?*DC@48}&zfy(2y
z>rBWU@G}B*5H+m@aE|nbISmufC}*J0vG{PvbdxK>=*mQ^MQ<;09t%N!Y*>EnpEELX
zXhKP833!!t)dK3+w=h=yXF@rK6Pk51OrOWTNhNmSY&FdlxR-o-AvtagBTd-nqh5jg
z$xNyM0jhoBl$1Ewe3)@xAC|N@g!Eii(R6GqUex|H^Gt_p3mo5sohh*hq~_7c@A|e}
z?=`eE?$0E9jE64apeg{K+fZO#M`_&>obQ5Lz`Qn~^i4h3_l4!o|LxL0nU^&F#Rrqg
z;H`PqpYsZ~O7X<&Q!>p35soVGQxZl#j1u()N_xZV=tYNLFFZtNv0?&QVO371W1|#j>f_4q<*n7)NCbvKhro%bDb~$ZSWuP`KPNf80`BuKCmB%
z_rIE67G_4KW{!heK&LfH)ZbIpCnKsh#SsU;=99b+qE@(wcLyPTq-eIj3*idZ#;o9s
zrpO(3Z_ks$!k$l(r|V{_AX+SJ&cEHAMYv{hn+Q1HRn&N*h&mCQ=MF)_31@N`9ght!L=!WhD#e{_
zQ~}KMOAz;Hc3tHG&J7@?Y~Fqy3%W@5;RO$^w!|s@oF*7|#hcBE3Hn5gc_fZ-Ma_*d
zcH2+QpFH(9pVPM!S(_~_wRi3BPx>{7@gh8H)Lmtjbgm{AMxUxa|67wJk
z@`={d@**4is8v%5doaO5YlPxyXG{#Bm%HSJ@{7bdmAl@i6CC|DWi(`{7NnKQMUjm<
zJ~o8*v*GYGT@==ERK4y8m?kumvVV0v%itioKulw&vf--g6SP7|_$}!LX)#QT3V*U6
z#@qlHhoJP*!vwsCECjBa>1)_cSPx`TR-Q_h^T)RVUyDP(Og$XPkw
z+*vNuW_kA#d1+S8oui*E@3~pOWLCaBIM2=AM%eqSYmx6W5o}3Ktd}NL6NuF_px{oL
zIKjFHCC)>FvEWR>3#%w_UR0J`F5k0M7%?VL)ybe
zVI`_1c^3u2IM=vMd&U~2oprA22FtSN&Z(QTec72Yf!{|N7ESvn?sDYrx_+?~I~)n;
zq|-odj;r}kOUy}b!~~Re9n;p7aBt}{lr?S->4S}v&TSk9Zdhq6HhaWh=2f^kJ~Ql3_~x70dhufJP+b=T#ksC=+tw&Jb1I$GzOBjn6oQ7Ny9V_lth=$j-UJc2vsv<@ei&
zNJug+fURbRpf{Bi7TAFWs)IAOcM>CM4a87KxqCO%sqD~%Fo9eJ)tC5+A3@TXZ}OB8
zW}2nQg`#MVrsq7Z{MKMlV_R;)g`oyt8p_VCho`o5)+g3~vVy*br{JQGmd8WpN6J={
zv{`T|IP(_NvSoq!XaPgiNLra>MSD(vR29hxRHPTjhf%7YS|X+-pNb4(P~j|5!J?>>
z!ZXA0$qRI~T7ES+SD_dP;pgs6moI-gf?`yL?XXRnj&Q3mf4K^W!w~q4hqMrt*WMwU
zJ5IObWs1QGUl=K+d&rds@bePnJM6(8Pi=Y37bQpu8`LDR$ZMC|ZQW30P$`AS*nH8~
zzVwuC0i9Xhp%TETt*rt%Z#|xNZW}ZLy=3l)h3PHeT
zEs*f8VACZ+evH14hh+5*nL_A4^o)W~@l%W(;k+AsoUtz-Fyxwl4Z?<6$y6J8_}w{k
zdc|jC5{c}6-VmFw^Wvo1JA#L@(SCf>q(7&z?bI`oBba(7EH5q2?|`R$cOs6XLJ+|`
zFf>|R=cU4wei=&IUV^HzB7a!t^6H>E9|V&1s{eE3kv1Qj6I)vVleMmzTybv(vrMMz
z>^GI>vS7@1Yv{u`b6D28d|zRs3Cfsa4JT4mwsD;48$}Z+_MVKg9kHPl!DR_h4#bXg
zGdS|wB?;apW9}JDg88bqyoWH`$8)Uam&MHlz|kR_A(LvFs!v1m)M
zLiIan7Dzp94>R>;+Rt#gS@4{UH+=M@@@@4YRcw#VPbg6w39Mh@d$>Cstk#(1L38Ep
zL9{~Lf^rGA?S)%^H1R8XKm{~YdYz!}!bJrLafjWJk;xGdkZGm7#@4dW;>-*rmYY%T6tJM
z(9EXUTuQj$C6`5-!e|QP=zTQaxYBUb3W(35i1;PfCmy)hO$X`32n
zgN_UxIXBA+{v%(=GFZF%vxN(<7D*HC$V-4-2OFV5v7Op(QBgNxQp
zb)Tvr+#Q!MY>O`D7L+Q=s2NMU4j@$NcAtBIQ^fhD}XV_oGqRBhKgznA>zbXxjBW
zjp^tmFHz1oT@)6eReOPPdc+NA=H(%0*klt6XP+)(;$rM>XLVkT9q*IJ0B33TX$WZr
z5a+rmVf*g+qQ19gv*kxt7x3XMHf_!JV0RRMvb%b;eyB1);x=Kkr8KD
zqx>c@6NFAN!!*P|mO-e;gsm&}Ou|Vk8x=6=2qo-rapzdSYUX)97-oeV$hSfM`w>Z`
zHCqkOCOz@$PWn7=+jE(>(`yr(ZCd-y<6fpMgO6~z%rm;P_PtTLjdLK%jD9&8m>!4V
zGj;sZnwjNO;a!F)Ob4}3(%I#As?JaM>znj+ULliEv1x@@>Lx~JlMeQM(Q7b5!Q&jX
z%WE)Hlq#CXKFs@}m@i{&A63QSv?a*!_?PaIFPO>o=ReV*xIIe;jQwuRY)$Ouf}^fP!Z(RG9ap>Mz)J(W55&@R&E2&tz1vSys!yXD?*~GM-~X~RV9{B0fPn@9
z@kaY!?F{}*7ysB9Olkt{_Qa8Yf1-XjvPwLvB9Tv1z(_22>S>K>7Yt}Upb--e@9fdH
zscyFx{x!F~m3sdi2ydC+RdNWw(tbNJ!D`pukq)tJ|BB>;h_r=rAc1l%dy5SRI~evo
zyB?-nxRr`S)}bZljP6Td3{J;&e|WQRw65Po3uFwOawr~YDu(pLGGv#ew4$NRp!-<8
za61U`v3S1)FTn%2W=Mg5NFamQY(ylLdW)RJisU^Ayr_u--3UmM@5q&y)kJMw7-MRf
zSd%FDO(p8M8mMEuL!kzVM5W3Nbw`Qp9Jz}O_j6~W^_hA&sEjO@ElT)?fRn;5f^Cgs
z)aFjd+bBqZ4SXt{VWoRM_%D@#Td)i9+c{nox^NnhGs{ZY$hX105%*rj0Gw<=hP8EH
z407MV-sv)`o2}8&FZB+o%v*_8?#k|7Hz=o{0(+TxYDk}`Wm=X-cB-v&W1gQdHKRDh
zZK9GWZA5C>iP={Dpn&L5BswnizEyDr1U*3`V}=KLouH+rYIpbo0Y)c1t%QjE3>yf=
z$@>Z_Ew_|t-`EJCh$ARx2&19;Pwjd8is7#$x;1x^`e$?C@hwFIU#T??5Yp&EEIu_W
zSJeg7m4@a_xszd%2y4_IrqOfL9g=F`kgH6o(Xb8bhyRJzK+|D<`zuUzA
zrp#
zT67=Y>N{`#mj-Z-uGFBAIMzXBeM8RP?6yV6>J`%OIyNx0S$^8)6rgg>X{gYb40@;`
zPhLO`A@nrLaE8VVn!?#R@lw~<)(xLm9HZ`m^bQTGq*L9pzVPtWq*-vrwlrEnv?88mDqW2R~Ds2emy-VW(t`Z*)AqxfwdA(34kz+ewb)YGi3)
z%LX+I4Zn6=7bg=O10xA}uVL^QztA3q_CaV9Db&*6(Euk0SVRcE&SIB))qz%HFp}ez
z5{mMN+NvhHa5?5Vs+*uSjpzl0yWvDZ1UolCV$n`vhFF$OLUBs(w>i&%{SE-nzj@j^
zng{g4_VuA9_CjHL%r%#l7+K6gU*}=rrovhNAqle1l9UG><
zmAH6AjP3PE6@g-&lF{|`o@DT}GZvgfDRQ6NW|Q3F|MX-m{a@5W=nVv%^rt&XL(W@MRp@G9Ht>k76u
z?5^y^IL_S1$={FLF(f=`<_?z6uHPW$R^Pi+P~K2k*@nm7zJQnnbR^
ziDUy@3^ov)%K~|QlGT;Hyig{VM(Tn*@V%3@z?QaJr`Z9a*_+udl^gfd6#f*CcPBl$
z&i7j3^3?;fEP3pbz^Oo*FY)E$Kl8ETmse+%p4HH62?hOj5gj?UYvZbg#1bpub4iLD
z8_v^zC0Gt-DJXPB78TEqy3&P>aAKQDL==W4$8=I^Jd9qIfyGn!L~=OQz?0Gh=dy9w
zebsVItatig3$WK>4UC-iI>+k+8B9o}nbxed=9?nDQyfBiilnTiZ8x}T58#96<$R-p
zf~DjAKvy~G%;w#2vx}rY-=kPC2w-c50pSC)e=Ls_EG)0hmEZ&$?Wb1?s`nP^5N6%T
zu1Mbykg`%ND5uBGL(O_qJ^VVMPmW7GvwbOajhu3{*Bwb^W#5V5=klc3q{S6=Mwy0t
z4C9`>ISR+%Z28esvtzlh^ZH_e@Tv_D{s4FOHY;zm>Cm&CbXUTrYMC!;#IJ~8{-%t23k0lIGz|$?_Q22uakjH+-e|W)NXo^7
z<7FynNl^*4+B*ZoQZ&43{VC+q+rz#Mw0lHz`y0M|qK`Q!D{%*1WjDBGJ1z3IUvfAM
zcxS
zj@-1AqtbA|PkGjkS&)sv)&SrWLG_vPpLuk-VKVW#9tjU)!n=67C-Evr;C>cpnLP}xH8WP!VQW{ho{IQQ)jjo6r0i&3NS!Sb
z)(qAua=aMv=V#mg+X!M}-$C=LLz%Z)3}O8Nb`R^Ij6Z--+hD!cZ5T67!auxiC2!Y9
zK^mw1JafBJP;Gt&)VviOKY^55&NcHv^W=1Pof@JoG-YGP?_EC3gdhY
z_M6<(6R*D~1H-!$j&OhDUC8twg5NPZ*@Cva(OtK`|44LqRQQDlh+Sw3kJa<${W(Uh
zx}i&DTT(xIFD^Ancq|bt*PCLjI+hRh!
zuuW