Merge remote-tracking branch 'eugenp/master'

This commit is contained in:
DOHA 2018-01-16 22:20:28 +02:00
commit 0d0e3dabc5
82 changed files with 2370 additions and 428 deletions

View File

@ -0,0 +1,44 @@
package com.baeldung.spliteratorAPI;
import java.util.List;
public class Article {
private List<Author> listOfAuthors;
private int id;
private String name;
public Article(String name) {
this.name = name;
}
public Article(List<Author> listOfAuthors, int id) {
super();
this.listOfAuthors = listOfAuthors;
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public List<Author> getListOfAuthors() {
return listOfAuthors;
}
public void setListOfAuthors(List<Author> listOfAuthors) {
this.listOfAuthors = listOfAuthors;
}
}

View File

@ -0,0 +1,33 @@
package com.baeldung.spliteratorAPI;
public class Author {
private String name;
private int relatedArticleId;
public Author(String name, int relatedArticleId) {
this.name = name;
this.relatedArticleId = relatedArticleId;
}
public int getRelatedArticleId() {
return relatedArticleId;
}
public void setRelatedArticleId(int relatedArticleId) {
this.relatedArticleId = relatedArticleId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "[name: " + name + ", relatedId: " + relatedArticleId + "]";
}
}

View File

@ -0,0 +1,45 @@
package com.baeldung.spliteratorAPI;
import java.util.Arrays;
import java.util.List;
import java.util.Spliterator;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
public class Executor {
public void executeCustomSpliterator() {
Article article = new Article(Arrays.asList(new Author("Ahmad", 0), new Author("Eugen", 0), new Author("Alice", 1), new Author("Alice", 1), new Author("Mike", 0), new Author("Alice", 1), new Author("Mike", 0), new Author("Alice", 1),
new Author("Mike", 0), new Author("Alice", 1), new Author("Mike", 0), new Author("Mike", 0), new Author("Alice", 1), new Author("Mike", 0), new Author("Alice", 1), new Author("Mike", 0), new Author("Alice", 1), new Author("Mike", 0),
new Author("Alice", 1), new Author("Mike", 0), new Author("Michał", 0), new Author("Loredana", 1)), 0);
Stream<Author> stream = IntStream.range(0, article.getListOfAuthors()
.size())
.mapToObj(article.getListOfAuthors()::get);
System.out.println("count= " + countAutors(stream.parallel()));
Spliterator<Author> spliterator = new RelatedAuthorSpliterator(article.getListOfAuthors());
Stream<Author> stream2 = StreamSupport.stream(spliterator, true);
System.out.println("count= " + countAutors(stream2.parallel()));
}
public void executeSpliterator() {
Spliterator<Article> split1 = generateElements().spliterator();
Spliterator<Article> split2 = split1.trySplit();
ExecutorService service = Executors.newCachedThreadPool();
service.execute(new Task(split1));
service.execute(new Task(split2));
}
private static int countAutors(Stream<Author> stream) {
RelatedAuthorCounter wordCounter = stream.reduce(new RelatedAuthorCounter(0, true), RelatedAuthorCounter::accumulate, RelatedAuthorCounter::combine);
return wordCounter.getCounter();
}
private List<Article> generateElements() {
return Stream.generate(() -> new Article("Java"))
.limit(35000)
.collect(Collectors.toList());
}
}

View File

@ -0,0 +1,27 @@
package com.baeldung.spliteratorAPI;
public class RelatedAuthorCounter {
private final int counter;
private final boolean isRelated;
public RelatedAuthorCounter(int counter, boolean isRelated) {
this.counter = counter;
this.isRelated = isRelated;
}
public RelatedAuthorCounter accumulate(Author author) {
if (author.getRelatedArticleId() == 0) {
return isRelated ? this : new RelatedAuthorCounter(counter, true);
} else {
return isRelated ? new RelatedAuthorCounter(counter + 1, false) : this;
}
}
public RelatedAuthorCounter combine(RelatedAuthorCounter RelatedAuthorCounter) {
return new RelatedAuthorCounter(counter + RelatedAuthorCounter.counter, RelatedAuthorCounter.isRelated);
}
public int getCounter() {
return counter;
}
}

View File

@ -0,0 +1,47 @@
package com.baeldung.spliteratorAPI;
import java.util.List;
import java.util.Spliterator;
import java.util.function.Consumer;
public class RelatedAuthorSpliterator implements Spliterator<Author> {
private final List<Author> list;
private int current = 0;
public RelatedAuthorSpliterator(List<Author> list) {
this.list = list;
}
@Override
public boolean tryAdvance(Consumer<? super Author> action) {
action.accept(list.get(current++));
return current < list.size();
}
@Override
public Spliterator<Author> trySplit() {
int currentSize = list.size() - current;
if (currentSize < 10) {
return null;
}
for (int splitPos = currentSize / 2 + current; splitPos < list.size(); splitPos++) {
if (list.get(splitPos)
.getRelatedArticleId() == 0) {
Spliterator<Author> spliterator = new RelatedAuthorSpliterator(list.subList(current, splitPos));
current = splitPos;
return spliterator;
}
}
return null;
}
@Override
public long estimateSize() {
return list.size() - current;
}
@Override
public int characteristics() {
return SIZED + CONCURRENT;
}
}

View File

@ -0,0 +1,26 @@
package com.baeldung.spliteratorAPI;
import java.util.Spliterator;
public class Task implements Runnable {
private Spliterator<Article> spliterator;
private final static String SUFFIX = "- published by Baeldung";
public Task(Spliterator<Article> spliterator) {
this.spliterator = spliterator;
}
@Override
public void run() {
int current = 0;
while (spliterator.tryAdvance(article -> {
article.setName(article.getName()
.concat(SUFFIX));
})) {
current++;
}
;
System.out.println(Thread.currentThread()
.getName() + ":" + current);
}
}

View File

@ -43,8 +43,9 @@ public class ControlSubThread implements Runnable {
try {
Thread.sleep(interval);
} catch (InterruptedException e) {
// no-op, just loop again
}
Thread.currentThread().interrupt();
System.out.println("Thread was interrupted, Failed to complete operation");
}
// do something
}
stopped.set(true);

View File

@ -44,6 +44,11 @@
<artifactId>kotlin-stdlib</artifactId>
<version>${kotlin-stdlib.version}</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jre8</artifactId>
<version>${kotlin-stdlib.version}</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-test-junit</artifactId>

View File

@ -0,0 +1,67 @@
package com.baeldung.kotlin
import org.junit.Test
import java.beans.ExceptionListener
import java.beans.XMLEncoder
import java.io.*
import java.lang.Exception
import kotlin.test.assertEquals
import kotlin.test.assertTrue
import kotlin.test.fail
class UseTest {
@Test
fun givenCloseable_whenUseIsCalled_thenItIsClosed() {
val stringWriter = StringWriter()
val writer = BufferedWriter(stringWriter) //Using a BufferedWriter because after close() it throws.
writer.use {
assertEquals(writer, it)
it.write("something")
}
try {
writer.write("something else")
fail("write() should have thrown an exception because the writer is closed.")
} catch (e: IOException) {
//Ok
}
assertEquals("something", stringWriter.toString())
}
@Test
fun givenAutoCloseable_whenUseIsCalled_thenItIsClosed() {
val baos = ByteArrayOutputStream()
val encoder = XMLEncoder(PrintStream(baos)) //XMLEncoder is AutoCloseable but not Closeable.
//Here, we use a PrintStream because after close() it throws.
encoder.exceptionListener = ThrowingExceptionListener()
encoder.use {
assertEquals(encoder, it)
it.writeObject("something")
}
try {
encoder.writeObject("something else")
encoder.flush()
fail("write() should have thrown an exception because the encoder is closed.")
} catch (e: IOException) {
//Ok
}
}
@Test
fun whenSimpleFormIsUsed_thenItWorks() {
StringWriter().use { it.write("something") }
}
}
class ThrowingExceptionListener : ExceptionListener {
override fun exceptionThrown(e: Exception?) {
if(e != null) {
throw e
}
}
}

View File

@ -55,7 +55,7 @@ public class InfluxDBConnectionLiveTest {
InfluxDB connection = connectDatabase();
// Create "baeldung and check for it
// Create "baeldung" and check for it
connection.createDatabase("baeldung");
assertTrue(connection.databaseExists("baeldung"));

View File

@ -0,0 +1,89 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>plugin</artifactId>
<version>2.33</version>
<relativePath />
</parent>
<artifactId>jenkins-hello-world</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>hpi</packaging>
<properties>
<!-- Baseline Jenkins version you use to build the plugin. Users must have this version or newer to run. -->
<jenkins.version>2.7.3</jenkins.version>
</properties>
<name>Hello World Plugin</name>
<description>A sample Jenkins Hello World plugin</description>
<url>https://wiki.jenkins-ci.org/display/JENKINS/TODO+Plugin</url>
<licenses>
<license>
<name>MIT License</name>
<url>http://opensource.org/licenses/MIT</url>
</license>
</licenses>
<dependencies>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>structs</artifactId>
<version>1.7</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-step-api</artifactId>
<version>2.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-cps</artifactId>
<version>2.39</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-job</artifactId>
<version>2.11.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-basic-steps</artifactId>
<version>2.6</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-durable-task-step</artifactId>
<version>2.13</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-api</artifactId>
<version>2.20</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-support</artifactId>
<version>2.14</version>
<scope>test</scope>
</dependency>
</dependencies>
<repositories>
<repository>
<id>repo.jenkins-ci.org</id>
<url>https://repo.jenkins-ci.org/public/</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>repo.jenkins-ci.org</id>
<url>https://repo.jenkins-ci.org/public/</url>
</pluginRepository>
</pluginRepositories>
</project>

View File

@ -0,0 +1,20 @@
package com.baeldung.jenkins.helloworld;
public class ProjectStats {
private final int classesNumber;
private final int linesNumber;
public ProjectStats(int classesNumber, int linesNumber) {
this.classesNumber = classesNumber;
this.linesNumber = linesNumber;
}
public int getClassesNumber() {
return classesNumber;
}
public int getLinesNumber() {
return linesNumber;
}
}

View File

@ -0,0 +1,123 @@
package com.baeldung.jenkins.helloworld;
import hudson.Extension;
import hudson.FilePath;
import hudson.Launcher;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.BuildListener;
import hudson.tasks.BuildWrapper;
import hudson.tasks.BuildWrapperDescriptor;
import org.kohsuke.stapler.DataBoundConstructor;
import javax.annotation.Nonnull;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Stack;
public class ProjectStatsBuildWrapper extends BuildWrapper {
private static final String REPORT_TEMPLATE_PATH = "/stats.html";
private static final String PROJECT_NAME_VAR = "$PROJECT_NAME$";
private static final String CLASSES_NUMBER_VAR = "$CLASSES_NUMBER$";
private static final String LINES_NUMBER_VAR = "$LINES_NUMBER$";
@DataBoundConstructor
public ProjectStatsBuildWrapper() {
}
@Override
public Environment setUp(AbstractBuild build, final Launcher launcher, BuildListener listener) {
return new Environment() {
@Override
public boolean tearDown(AbstractBuild build, BuildListener listener)
throws IOException, InterruptedException
{
ProjectStats stats = buildStats(build.getWorkspace());
String report = generateReport(build.getProject().getDisplayName(), stats);
File artifactsDir = build.getArtifactsDir();
if (!artifactsDir.isDirectory()) {
boolean success = artifactsDir.mkdirs();
if (!success) {
listener.getLogger().println("Can't create artifacts directory at "
+ artifactsDir.getAbsolutePath());
}
}
String path = artifactsDir.getCanonicalPath() + REPORT_TEMPLATE_PATH;
try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path),
StandardCharsets.UTF_8))) {
writer.write(report);
}
return super.tearDown(build, listener);
}
};
}
private static ProjectStats buildStats(FilePath root) throws IOException, InterruptedException {
int classesNumber = 0;
int linesNumber = 0;
Stack<FilePath> toProcess = new Stack<>();
toProcess.push(root);
while (!toProcess.isEmpty()) {
FilePath path = toProcess.pop();
if (path.isDirectory()) {
toProcess.addAll(path.list());
} else if (path.getName().endsWith(".java")) {
classesNumber++;
linesNumber += countLines(path);
}
}
return new ProjectStats(classesNumber, linesNumber);
}
private static int countLines(FilePath path) throws IOException, InterruptedException {
byte[] buffer = new byte[1024];
int result = 1;
try (InputStream in = path.read()) {
while (true) {
int read = in.read(buffer);
if (read < 0) {
return result;
}
for (int i = 0; i < read; i++) {
if (buffer[i] == '\n') {
result++;
}
}
}
}
}
private static String generateReport(String projectName, ProjectStats stats) throws IOException {
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
try (InputStream in = ProjectStatsBuildWrapper.class.getResourceAsStream(REPORT_TEMPLATE_PATH)) {
byte[] buffer = new byte[1024];
int read;
while ((read = in.read(buffer)) >= 0) {
bOut.write(buffer, 0, read);
}
}
String content = new String(bOut.toByteArray(), StandardCharsets.UTF_8);
content = content.replace(PROJECT_NAME_VAR, projectName);
content = content.replace(CLASSES_NUMBER_VAR, String.valueOf(stats.getClassesNumber()));
content = content.replace(LINES_NUMBER_VAR, String.valueOf(stats.getLinesNumber()));
return content;
}
@Extension
public static final class DescriptorImpl extends BuildWrapperDescriptor {
@Override
public boolean isApplicable(AbstractProject<?, ?> item) {
return true;
}
@Nonnull
@Override
public String getDisplayName() {
return "Construct project stats during build";
}
}
}

View File

@ -0,0 +1,20 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>$PROJECT_NAME$</title>
</head>
<body>
Project $PROJECT_NAME$:
<table border="1">
<tr>
<th>Classes number</th>
<th>Lines number</th>
</tr>
<tr>
<td>$CLASSES_NUMBER$</td>
<td>$LINES_NUMBER$</td>
</tr>
</table>
</body>
</html>

View File

@ -1,3 +1,5 @@
### Relevant Articles:
- [Intro to Jedis the Java Redis Client Library](http://www.baeldung.com/jedis-java-redis-client-library)
- [A Guide to Redis with Redisson](http://www.baeldung.com/redis-redisson)
- [Intro to Lettuce the Java Redis Client Library](http://www.baeldung.com/lettuce-java-redis-client-library)

View File

@ -36,6 +36,13 @@
<artifactId>redisson</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
<version>5.0.1.RELEASE</version>
</dependency>
</dependencies>
<properties>

View File

@ -0,0 +1,312 @@
package com.baeldung;
import io.lettuce.core.LettuceFutures;
import io.lettuce.core.RedisClient;
import io.lettuce.core.RedisFuture;
import io.lettuce.core.TransactionResult;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.async.RedisAsyncCommands;
import io.lettuce.core.api.sync.RedisCommands;
import io.lettuce.core.pubsub.RedisPubSubListener;
import io.lettuce.core.pubsub.StatefulRedisPubSubConnection;
import io.lettuce.core.pubsub.api.async.RedisPubSubAsyncCommands;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import static org.junit.Assert.assertTrue;
public class LettuceIntegrationLiveTest {
private static Logger log = LoggerFactory.getLogger(LettuceIntegrationLiveTest.class);
private static StatefulRedisConnection<String, String> redisConnection;
private static RedisClient redisClient;
@BeforeClass
public static void setUp() {
// Docker defaults to mapping redis port to 32768
redisClient = RedisClient.create("redis://localhost:32768/");
redisConnection = redisClient.connect();
}
@AfterClass
public static void destroy() {
redisConnection.close();
}
@Test
public void givenAString_thenSaveItAsRedisStringsSync() {
RedisCommands<String, String> syncCommands = redisConnection.sync();
String key = "key";
String value = "value";
syncCommands.set(key, value);
String response = syncCommands.get(key);
Assert.assertEquals(value, response);
}
@Test
public void givenValues_thenSaveAsRedisHashSync() {
RedisCommands<String, String> syncCommands = redisConnection.sync();
String recordName = "record1";
String name = "FirstName";
String value = "John";
String surname = "LastName";
String value1 = "Smith";
syncCommands.hset(recordName, name, value);
syncCommands.hset(recordName, surname, value1);
Map<String, String> record = syncCommands.hgetall(recordName);
Assert.assertEquals(record.get(name), value);
Assert.assertEquals(record.get(surname), value1);
}
@Test
public void givenAString_thenSaveItAsRedisStringsAsync() throws Exception {
RedisAsyncCommands<String, String> asyncCommands = redisConnection.async();
String key = "key";
String value = "value";
asyncCommands.set(key, value);
RedisFuture<String> redisFuture = asyncCommands.get(key);
String response = redisFuture.get();
Assert.assertEquals(value, response);
}
@Test
public void givenValues_thenSaveAsRedisHashAsync() throws Exception {
RedisAsyncCommands<String, String> asyncCommands = redisConnection.async();
String recordName = "record1";
String name = "FirstName";
String value = "John";
String surname = "LastName";
String value1 = "Smith";
asyncCommands.hset(recordName, name, value);
asyncCommands.hset(recordName, surname, value1);
RedisFuture<Map<String, String>> redisFuture = asyncCommands.hgetall(recordName);
Map<String, String> record = redisFuture.get();
Assert.assertEquals(record.get(name), value);
Assert.assertEquals(record.get(surname), value1);
}
@Test
public void givenValues_thenSaveAsRedisListAsync() throws Exception {
RedisAsyncCommands<String, String> asyncCommands = redisConnection.async();
String listName = "tasks";
String firstTask = "firstTask";
String secondTask = "secondTask";
asyncCommands.del(listName);
asyncCommands.lpush(listName, firstTask);
asyncCommands.lpush(listName, secondTask);
RedisFuture<String> redisFuture = asyncCommands.rpop(listName);
String nextTask = redisFuture.get();
Assert.assertEquals(firstTask, nextTask);
asyncCommands.del(listName);
asyncCommands.lpush(listName, firstTask);
asyncCommands.lpush(listName, secondTask);
redisFuture = asyncCommands.lpop(listName);
nextTask = redisFuture.get();
Assert.assertEquals(secondTask, nextTask);
}
@Test
public void givenSetElements_thenSaveThemInRedisSetAsync() throws Exception {
RedisAsyncCommands<String, String> asyncCommands = redisConnection.async();
String countries = "countries";
String countryOne = "Spain";
String countryTwo = "Ireland";
String countryThree = "Ireland";
asyncCommands.sadd(countries, countryOne);
RedisFuture<Set<String>> countriesSetFuture = asyncCommands.smembers(countries);
Assert.assertEquals(2, countriesSetFuture.get().size());
asyncCommands.sadd(countries, countryTwo);
countriesSetFuture = asyncCommands.smembers(countries);
Assert.assertEquals(2, countriesSetFuture.get().size());
asyncCommands.sadd(countries, countryThree);
countriesSetFuture = asyncCommands.smembers(countries);
Assert.assertEquals(2, countriesSetFuture.get().size());
RedisFuture<Boolean> exists = asyncCommands.sismember(countries, countryThree);
assertTrue(exists.get());
}
@Test
public void givenARanking_thenSaveItInRedisSortedSetAsync() throws Exception {
RedisAsyncCommands<String, String> asyncCommands = redisConnection.async();
String key = "sortedset";
asyncCommands.zadd(key, 1, "one");
asyncCommands.zadd(key, 4, "zero");
asyncCommands.zadd(key, 2, "two");
RedisFuture<List<String>> values = asyncCommands.zrevrange(key, 0, 3);
Assert.assertEquals("zero", values.get().get(0));
values = asyncCommands.zrange(key, 0, 3);
Assert.assertEquals("one", values.get().get(0));
}
@Test
public void givenMultipleOperationsThatNeedToBeExecutedAtomically_thenWrapThemInATransaction() throws Exception {
RedisAsyncCommands<String, String> asyncCommands = redisConnection.async();
// Start a transaction
asyncCommands.multi();
// Add three sets to it, and save the future responses
RedisFuture<String> result1 = asyncCommands.set("key1", "value1");
RedisFuture<String> result2 = asyncCommands.set("key2", "value2");
RedisFuture<String> result3 = asyncCommands.set("key3", "value3");
// Execute it
RedisFuture<TransactionResult> execResult = asyncCommands.exec();
TransactionResult transactionResult = execResult.get();
// Get the three results in the transaction return
String firstResult = transactionResult.get(0);
String secondResult = transactionResult.get(0);
String thirdResult = transactionResult.get(0);
// Our results are in both!
assertTrue(firstResult.equals("OK"));
assertTrue(secondResult.equals("OK"));
assertTrue(thirdResult.equals("OK"));
assertTrue(result1.get().equals("OK"));
assertTrue(result2.get().equals("OK"));
assertTrue(result3.get().equals("OK"));
}
@Test
public void givenMultipleIndependentOperations_whenNetworkOptimizationIsImportant_thenFlushManually() throws Exception {
int iterations = 50;
RedisAsyncCommands<String, String> asyncCommands = redisConnection.async();
asyncCommands.setAutoFlushCommands(false);
List<RedisFuture<?>> futures = new ArrayList<>();
for (int i = 0; i < iterations; i++) {
futures.add(asyncCommands.set("key" + i, "value" + i));
}
asyncCommands.flushCommands();
// Wait until all futures complete
boolean result = LettuceFutures.awaitAll(5, TimeUnit.SECONDS, futures.toArray(new RedisFuture[futures.size()]));
asyncCommands.setAutoFlushCommands(true);
}
@Test
public void givenPubSubChannel_whenMessage_thenMessageReceived() throws Exception {
Listener listener = new Listener();
StatefulRedisPubSubConnection<String, String> connection = redisClient.connectPubSub();
StatefulRedisPubSubConnection<String, String> pubconnection = redisClient.connectPubSub();
connection.addListener(listener);
RedisPubSubAsyncCommands<String, String> async = connection.async();
async.subscribe("channel");
RedisPubSubAsyncCommands<String, String> pubasync = pubconnection.async();
RedisFuture<Long> result = pubasync.publish("channel", "hithere");
// Need a long wait for publish to complete, depending on system.
result.get(15, TimeUnit.SECONDS);
assertTrue(listener.getMessage().equals("hithere"));
}
private static class Listener implements RedisPubSubListener<String, String> {
private String message;
String getMessage() {
return message;
}
@Override
public void message(String channel, String message) {
log.debug("Got {} on {}", message, channel);
this.message = message;
}
@Override
public void message(String pattern, String channel, String message) {
}
@Override
public void subscribed(String channel, long count) {
log.debug("Subscribed to {}", channel);
}
@Override
public void psubscribed(String pattern, long count) {
}
@Override
public void unsubscribed(String channel, long count) {
}
@Override
public void punsubscribed(String pattern, long count) {
}
}
}

View File

@ -43,6 +43,10 @@
<groupId>javax.json.bind</groupId>
<artifactId>javax.json.bind-api</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- Dependencies for Yasson -->
<!-- <dependency> -->
@ -198,4 +202,5 @@
<geronimo-json_1.1_spec.version>1.0</geronimo-json_1.1_spec.version>
</properties>
</project>

View File

@ -1,4 +1,4 @@
package com.baeldung.actuator;
package com.baeldung.reactive.actuator;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.ReactiveHealthIndicator;

View File

@ -1,4 +1,4 @@
package com.baeldung.actuator;
package com.baeldung.reactive.actuator;
import org.springframework.boot.actuate.endpoint.annotation.*;
import org.springframework.stereotype.Component;

View File

@ -1,4 +1,4 @@
package com.baeldung.actuator;
package com.baeldung.reactive.actuator;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import org.springframework.boot.actuate.endpoint.web.WebEndpointResponse;

View File

@ -1 +1,4 @@
logging.level.root=INFO
logging.level.root=INFO
management.endpoints.web.expose=*
info.app.name=Spring Boot 2 actuator Application

View File

@ -1,6 +1,5 @@
package com.baeldung.actuator;
package com.baeldung.reactive.actuator;
import com.baeldung.jsonb.Spring5Application;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
@ -10,12 +9,14 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit4.SpringRunner;
import com.baeldung.reactive.Spring5ReactiveApplication;
import java.io.IOException;
import static org.junit.Assert.assertEquals;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Spring5Application.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Spring5ReactiveApplication.class)
public class ActuatorInfoIntegrationTest {
@Autowired

View File

@ -0,0 +1,3 @@
## Relevant articles:
- [Spring Security 5 -OAuth2 Login](http://www.baeldung.com/spring-security-5-oauth2-login)

View File

@ -43,10 +43,6 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-hateoas</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.projectreactor</groupId>
<artifactId>reactor-spring</artifactId>

View File

@ -17,7 +17,6 @@ public class SecurityConfig {
public SecurityWebFilterChain securitygWebFilterChain(ServerHttpSecurity http) {
return http.authorizeExchange()
.pathMatchers("/admin").hasAuthority("ROLE_ADMIN")
.pathMatchers("/actuator/**").permitAll()
.anyExchange().authenticated()
.and().formLogin()
.and().build();

View File

@ -1,5 +1,3 @@
server.port=8081
management.endpoints.web.expose=*
info.app.name=Spring Boot 2 actuator Application
logging.level.root=INFO

View File

@ -1,6 +1,8 @@
### Spring Boot Security Auto-Configuration
- mvn clean install
- uncomment in application.properties spring.profiles.active=basic # for basic auth config
- uncomment in application.properties spring.profiles.active=form # for form based auth config
- uncomment actuator dependency simultaneously with the line from main class
- uncomment actuator dependency simultaneously with the line from basic auth main class
- uncomment security properties for easy testing. If not random will be generated.
### CURL commands
- curl -X POST -u baeldung-admin:baeldung -d grant_type=client_credentials -d username=baeldung-admin -d password=baeldung http://localhost:8080/oauth/token

View File

@ -43,6 +43,10 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>

View File

@ -1,4 +1,4 @@
package com.baeldung.springbootsecurity;
package com.baeldung.springbootsecurity.basic_auth;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@ -7,7 +7,7 @@ import org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration
@SpringBootApplication(exclude = {
SecurityAutoConfiguration.class
// ,ManagementWebSecurityAutoConfiguration.class
})
}, scanBasePackages = "com.baeldung.springbootsecurity.basic_auth")
public class SpringBootSecurityApplication {
public static void main(String[] args) {

View File

@ -1,7 +1,6 @@
package com.baeldung.springbootsecurity.config;
package com.baeldung.springbootsecurity.basic_auth.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
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;
@ -9,8 +8,7 @@ import org.springframework.security.config.annotation.web.configuration.WebSecur
@Configuration
@EnableWebSecurity
@Profile("basic")
public class BasicConfiguration extends WebSecurityConfigurerAdapter {
public class BasicAuthConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {

View File

@ -1,39 +0,0 @@
package com.baeldung.springbootsecurity.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
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;
@Configuration
@EnableWebSecurity
@Profile("form")
public class FormLoginConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user")
.password("password")
.roles("USER")
.and()
.withUser("admin")
.password("password")
.roles("USER", "ADMIN");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.formLogin()
.and()
.httpBasic();
}
}

View File

@ -0,0 +1,30 @@
package com.baeldung.springbootsecurity.oauth2resource;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@EnableResourceServer
@SpringBootApplication(scanBasePackages = "com.baeldung.springbootsecurity.oauth2resource")
public class SpringBootOAuth2ResourceApplication {
public static void main(String[] args) {
new SpringApplicationBuilder()
.profiles("resource")
.sources(SpringBootOAuth2ResourceApplication.class)
.build()
.run(args);
}
@RestController
class SecuredResourceController {
@GetMapping("/securedResource")
public String securedResource() {
return "Baeldung Secured Resource OK";
}
}
}

View File

@ -0,0 +1,30 @@
package com.baeldung.springbootsecurity.oauth2server;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.security.Principal;
@EnableResourceServer
@EnableAuthorizationServer
@SpringBootApplication(scanBasePackages = "com.baeldung.springbootsecurity.oauth2server")
public class SpringBootAuthorizationServerApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootAuthorizationServerApplication.class, args);
}
@RestController
class UserController {
@GetMapping("/user")
public Principal user(Principal user) {
return user;
}
}
}

View File

@ -0,0 +1,39 @@
package com.baeldung.springbootsecurity.oauth2server.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
@Configuration
@Profile("authz")
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager);
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
.inMemory()
.withClient("baeldung")
.secret("baeldung")
.authorizedGrantTypes("client_credentials", "password", "authorization_code")
.scopes("openid", "read")
.autoApprove(true)
.and()
.withClient("baeldung-admin")
.secret("baeldung")
.authorizedGrantTypes("authorization_code", "client_credentials", "refresh_token")
.scopes("read", "write")
.autoApprove(true);
}
}

View File

@ -0,0 +1,18 @@
package com.baeldung.springbootsecurity.oauth2sso;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso;
import org.springframework.boot.builder.SpringApplicationBuilder;
@EnableOAuth2Sso
@SpringBootApplication(scanBasePackages = "com.baeldung.springbootsecurity.oauth2sso")
public class SpringBootOAuth2SsoApplication {
public static void main(String[] args) {
new SpringApplicationBuilder()
.profiles("sso")
.sources(SpringBootOAuth2SsoApplication.class)
.build()
.run(args);
}
}

View File

@ -0,0 +1,3 @@
security.user.password=password
security.oauth2.client.client-id=client
security.oauth2.client.client-secret=secret

View File

@ -0,0 +1,2 @@
server.port=8081
security.oauth2.resource.userInfoUri=http://localhost:8080/user

View File

@ -0,0 +1,9 @@
server.port=8082
security.oauth2.client.clientId=<generated_app_id>
security.oauth2.client.clientSecret=<app_secret>
security.oauth2.client.accessTokenUri=https://graph.facebook.com/oauth/access_token
security.oauth2.client.userAuthorizationUri=https://www.facebook.com/dialog/oauth
security.oauth2.client.tokenName=oauth_token
security.oauth2.client.authenticationScheme=query
security.oauth2.client.clientAuthenticationScheme=form
security.oauth2.resource.userInfoUri=https://graph.facebook.com/me

View File

@ -1,4 +1,4 @@
#spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration
#spring.profiles.active=form
#spring.profiles.active=basic
#security.user.password=password
#security.user.password=password
#security.oauth2.client.client-id=client
#security.oauth2.client.client-secret=secret

View File

@ -1,106 +0,0 @@
package com.baeldung.springbootsecurity;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.embedded.LocalServerPort;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.*;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import java.util.Collections;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static org.junit.Assert.*;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = RANDOM_PORT)
@ActiveProfiles("form")
public class FormConfigurationIntegrationTest {
@Autowired TestRestTemplate restTemplate;
@LocalServerPort int port;
@Test
public void whenLoginPageIsRequested_ThenSuccess() {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setAccept(Collections.singletonList(MediaType.TEXT_HTML));
ResponseEntity<String> responseEntity = restTemplate.exchange("/login", HttpMethod.GET, new HttpEntity<Void>(httpHeaders), String.class);
assertEquals(HttpStatus.OK, responseEntity.getStatusCode());
assertTrue(responseEntity
.getBody()
.contains("_csrf"));
}
@Test
public void whenTryingToLoginWithCorrectCredentials_ThenAuthenticateWithSuccess() {
HttpHeaders httpHeaders = getHeaders();
httpHeaders.setAccept(Collections.singletonList(MediaType.TEXT_HTML));
httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
MultiValueMap<String, String> form = getFormSubmitCorrectCredentials();
ResponseEntity<String> responseEntity = this.restTemplate.exchange("/login", HttpMethod.POST, new HttpEntity<>(form, httpHeaders), String.class);
assertEquals(responseEntity.getStatusCode(), HttpStatus.FOUND);
assertTrue(responseEntity
.getHeaders()
.getLocation()
.toString()
.endsWith(this.port + "/"));
assertNotNull(responseEntity
.getHeaders()
.get("Set-Cookie"));
}
@Test
public void whenTryingToLoginWithInorrectCredentials_ThenAuthenticationFailed() {
HttpHeaders httpHeaders = getHeaders();
httpHeaders.setAccept(Collections.singletonList(MediaType.TEXT_HTML));
httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
MultiValueMap<String, String> form = getFormSubmitIncorrectCredentials();
ResponseEntity<String> responseEntity = this.restTemplate.exchange("/login", HttpMethod.POST, new HttpEntity<>(form, httpHeaders), String.class);
assertEquals(responseEntity.getStatusCode(), HttpStatus.FOUND);
assertTrue(responseEntity
.getHeaders()
.getLocation()
.toString()
.endsWith(this.port + "/login?error"));
assertNull(responseEntity
.getHeaders()
.get("Set-Cookie"));
}
private MultiValueMap<String, String> getFormSubmitCorrectCredentials() {
MultiValueMap<String, String> form = new LinkedMultiValueMap<>();
form.set("username", "user");
form.set("password", "password");
return form;
}
private MultiValueMap<String, String> getFormSubmitIncorrectCredentials() {
MultiValueMap<String, String> form = new LinkedMultiValueMap<>();
form.set("username", "user");
form.set("password", "wrongpassword");
return form;
}
private HttpHeaders getHeaders() {
HttpHeaders headers = new HttpHeaders();
ResponseEntity<String> page = this.restTemplate.getForEntity("/login", String.class);
assertEquals(page.getStatusCode(), HttpStatus.OK);
String cookie = page
.getHeaders()
.getFirst("Set-Cookie");
headers.set("Cookie", cookie);
Pattern pattern = Pattern.compile("(?s).*name=\"_csrf\".*?value=\"([^\"]+).*");
Matcher matcher = pattern.matcher(page.getBody());
assertTrue(matcher.matches());
headers.set("X-CSRF-TOKEN", matcher.group(1));
return headers;
}
}

View File

@ -1,5 +1,6 @@
package com.baeldung.springbootsecurity;
package com.baeldung.springbootsecurity.basic_auth;
import com.baeldung.springbootsecurity.basic_auth.SpringBootSecurityApplication;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -8,7 +9,6 @@ import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
import java.io.IOException;
@ -20,9 +20,8 @@ import static org.junit.Assert.assertTrue;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = RANDOM_PORT)
@ActiveProfiles("basic")
public class BasicConfigurationIntegrationTest {
@SpringBootTest(webEnvironment = RANDOM_PORT, classes = SpringBootSecurityApplication.class)
public class BasicAuthConfigurationIntegrationTest {
TestRestTemplate restTemplate;
URL base;

View File

@ -0,0 +1,75 @@
package com.baeldung.springbootsecurity.oauth2server;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.security.oauth2.client.DefaultOAuth2ClientContext;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
import org.springframework.security.oauth2.client.resource.OAuth2AccessDeniedException;
import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsResourceDetails;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
import static java.lang.String.format;
import static java.util.Collections.singletonList;
import static org.junit.Assert.assertNotNull;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = RANDOM_PORT, classes = SpringBootAuthorizationServerApplication.class)
@ActiveProfiles("authz")
public class CustomConfigAuthorizationServerIntegrationTest {
@Value("${local.server.port}") protected int port;
@Test
public void whenAccessTokenIsRequested_ThenAccessTokenValueIsNotNull() {
ClientCredentialsResourceDetails resourceDetails = getClientCredentialsResourceDetails();
resourceDetails.setClientId("baeldung");
resourceDetails.setClientSecret("baeldung");
resourceDetails.setScope(singletonList("read"));
DefaultOAuth2ClientContext clientContext = new DefaultOAuth2ClientContext();
OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(resourceDetails, clientContext);
restTemplate.setMessageConverters(singletonList(new MappingJackson2HttpMessageConverter()));
OAuth2AccessToken accessToken = restTemplate.getAccessToken();
assertNotNull(accessToken);
}
@Test(expected = OAuth2AccessDeniedException.class)
public void whenAccessTokenIsRequestedWithInvalidException_ThenExceptionIsThrown() {
ClientCredentialsResourceDetails resourceDetails = getClientCredentialsResourceDetails();
resourceDetails.setClientId("baeldung");
resourceDetails.setClientSecret("baeldung");
resourceDetails.setScope(singletonList("write"));
DefaultOAuth2ClientContext clientContext = new DefaultOAuth2ClientContext();
OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(resourceDetails, clientContext);
restTemplate.setMessageConverters(singletonList(new MappingJackson2HttpMessageConverter()));
restTemplate.getAccessToken();
}
@Test
public void whenAccessTokenIsRequestedByClientWithWriteScope_ThenAccessTokenIsNotNull() {
ClientCredentialsResourceDetails resourceDetails = getClientCredentialsResourceDetails();
resourceDetails.setClientId("baeldung-admin");
resourceDetails.setClientSecret("baeldung");
resourceDetails.setScope(singletonList("write"));
DefaultOAuth2ClientContext clientContext = new DefaultOAuth2ClientContext();
OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(resourceDetails, clientContext);
restTemplate.setMessageConverters(singletonList(new MappingJackson2HttpMessageConverter()));
OAuth2AccessToken accessToken = restTemplate.getAccessToken();
assertNotNull(accessToken);
}
private ClientCredentialsResourceDetails getClientCredentialsResourceDetails() {
ClientCredentialsResourceDetails resourceDetails = new ClientCredentialsResourceDetails();
resourceDetails.setAccessTokenUri(format("http://localhost:%d/oauth/token", port));
resourceDetails.setGrantType("client_credentials");
return resourceDetails;
}
}

View File

@ -0,0 +1,44 @@
package com.baeldung.springbootsecurity.oauth2server;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.security.oauth2.client.DefaultOAuth2ClientContext;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsResourceDetails;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.test.context.junit4.SpringRunner;
import static java.lang.String.format;
import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
import static org.junit.Assert.assertNotNull;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = RANDOM_PORT, classes = SpringBootAuthorizationServerApplication.class,
properties = { "security.oauth2.client.client-id=client", "security.oauth2.client.client-secret=secret" })
public class DefaultConfigAuthorizationServerIntegrationTest {
@Value("${local.server.port}") protected int port;
@Test
public void whenAccessTokenIsRequested_ThenAccessTokenValueIsNotNull() {
ClientCredentialsResourceDetails resourceDetails = new ClientCredentialsResourceDetails();
resourceDetails.setAccessTokenUri(format("http://localhost:%d/oauth/token", port));
resourceDetails.setClientId("client");
resourceDetails.setClientSecret("secret");
resourceDetails.setGrantType("client_credentials");
resourceDetails.setScope(asList("read", "write"));
DefaultOAuth2ClientContext clientContext = new DefaultOAuth2ClientContext();
OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(resourceDetails, clientContext);
restTemplate.setMessageConverters(singletonList(new MappingJackson2HttpMessageConverter()));
OAuth2AccessToken accessToken = restTemplate.getAccessToken();
assertNotNull(accessToken);
}
}

View File

@ -45,6 +45,24 @@
<version>${spring-data-elasticsearch.version}</version>
</dependency>
<dependency>
<groupId>com.spatial4j</groupId>
<artifactId>spatial4j</artifactId>
<version>0.4.1</version>
</dependency>
<dependency>
<groupId>com.vividsolutions</groupId>
<artifactId>jts</artifactId>
<version>1.13</version>
<exclusions>
<exclusion>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>

View File

@ -0,0 +1,179 @@
package com.baeldung.elasticsearch;
import static org.junit.Assert.assertTrue;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.geo.ShapeRelation;
import org.elasticsearch.common.geo.builders.ShapeBuilder;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.baeldung.spring.data.es.config.Config;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = Config.class)
public class GeoQueriesTest {
public static final String WONDERS_OF_WORLD = "wonders-of-world";
public static final String WONDERS = "Wonders";
@Autowired
private ElasticsearchTemplate elasticsearchTemplate;
@Autowired
private Client client;
@Before
public void setUp() {
String jsonObject = "{\"Wonders\":{\"properties\":{\"name\":{\"type\":\"string\",\"index\":\"not_analyzed\"},\"region\":{\"type\":\"geo_shape\",\"tree\":\"quadtree\",\"precision\":\"1m\"},\"location\":{\"type\":\"geo_point\"}}}}";
CreateIndexRequest req = new CreateIndexRequest(WONDERS_OF_WORLD);
req.mapping(WONDERS, jsonObject);
client.admin()
.indices()
.create(req)
.actionGet();
}
@Test
public void givenGeoShapeData_whenExecutedGeoShapeQuery_thenResultNonEmpty() {
String jsonObject = "{\"name\":\"Agra\",\"region\":{\"type\":\"envelope\",\"coordinates\":[[75,25],[80.1,30.2]]}}";
IndexResponse response = client.prepareIndex(WONDERS_OF_WORLD, WONDERS)
.setSource(jsonObject)
.get();
String tajMahalId = response.getId();
client.admin()
.indices()
.prepareRefresh(WONDERS_OF_WORLD)
.get();
QueryBuilder qb = QueryBuilders.geoShapeQuery("region", ShapeBuilder.newEnvelope()
.topLeft(74.00, 24.0)
.bottomRight(81.1, 31.2))
.relation(ShapeRelation.WITHIN);
SearchResponse searchResponse = client.prepareSearch(WONDERS_OF_WORLD)
.setTypes(WONDERS)
.setQuery(qb)
.execute()
.actionGet();
List<String> ids = Arrays.stream(searchResponse.getHits()
.getHits())
.map(hit -> {
return hit.getId();
})
.collect(Collectors.toList());
assertTrue(ids.contains(tajMahalId));
}
@Test
public void givenGeoPointData_whenExecutedGeoBoundingBoxQuery_thenResultNonEmpty() {
String jsonObject = "{\"name\":\"Pyramids of Giza\",\"location\":[31.131302,29.976480]}";
IndexResponse response = client.prepareIndex(WONDERS_OF_WORLD, WONDERS)
.setSource(jsonObject)
.get();
String pyramidsOfGizaId = response.getId();
client.admin()
.indices()
.prepareRefresh(WONDERS_OF_WORLD)
.get();
QueryBuilder qb = QueryBuilders.geoBoundingBoxQuery("location")
.bottomLeft(28, 30)
.topRight(31, 32);
SearchResponse searchResponse = client.prepareSearch(WONDERS_OF_WORLD)
.setTypes(WONDERS)
.setQuery(qb)
.execute()
.actionGet();
List<String> ids = Arrays.stream(searchResponse.getHits()
.getHits())
.map(hit -> {
return hit.getId();
})
.collect(Collectors.toList());
assertTrue(ids.contains(pyramidsOfGizaId));
}
@Test
public void givenGeoPointData_whenExecutedGeoDistanceQuery_thenResultNonEmpty() {
String jsonObject = "{\"name\":\"Lighthouse of alexandria\",\"location\":[31.131302,29.976480]}";
IndexResponse response = client.prepareIndex(WONDERS_OF_WORLD, WONDERS)
.setSource(jsonObject)
.get();
String lighthouseOfAlexandriaId = response.getId();
client.admin()
.indices()
.prepareRefresh(WONDERS_OF_WORLD)
.get();
QueryBuilder qb = QueryBuilders.geoDistanceQuery("location")
.point(29.976, 31.131)
.distance(10, DistanceUnit.MILES);
SearchResponse searchResponse = client.prepareSearch(WONDERS_OF_WORLD)
.setTypes(WONDERS)
.setQuery(qb)
.execute()
.actionGet();
List<String> ids = Arrays.stream(searchResponse.getHits()
.getHits())
.map(hit -> {
return hit.getId();
})
.collect(Collectors.toList());
assertTrue(ids.contains(lighthouseOfAlexandriaId));
}
@Test
public void givenGeoPointData_whenExecutedGeoPolygonQuery_thenResultNonEmpty() {
String jsonObject = "{\"name\":\"The Great Rann of Kutch\",\"location\":[69.859741,23.733732]}";
IndexResponse response = client.prepareIndex(WONDERS_OF_WORLD, WONDERS)
.setSource(jsonObject)
.get();
String greatRannOfKutchid = response.getId();
client.admin()
.indices()
.prepareRefresh(WONDERS_OF_WORLD)
.get();
QueryBuilder qb = QueryBuilders.geoPolygonQuery("location")
.addPoint(22.733, 68.859)
.addPoint(24.733, 68.859)
.addPoint(23, 70.859);
SearchResponse searchResponse = client.prepareSearch(WONDERS_OF_WORLD)
.setTypes(WONDERS)
.setQuery(qb)
.execute()
.actionGet();
List<String> ids = Arrays.stream(searchResponse.getHits()
.getHits())
.map(hit -> {
return hit.getId();
})
.collect(Collectors.toList());
assertTrue(ids.contains(greatRannOfKutchid));
}
@After
public void destroy() {
elasticsearchTemplate.deleteIndex(WONDERS_OF_WORLD);
}
}

View File

@ -110,7 +110,7 @@
<properties>
<!-- Spring -->
<org.springframework.version>4.3.4.RELEASE</org.springframework.version>
<org.springframework.version>5.0.2.RELEASE</org.springframework.version>
<org.springframework.security.version>4.2.0.RELEASE</org.springframework.security.version>
<!-- persistence -->
@ -142,4 +142,4 @@
</properties>
</project>
</project>

View File

@ -8,24 +8,14 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ExampleOne extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println(
"<!DOCTYPE html><html>" +
"<head>" +
"<meta charset=\"UTF-8\" />" +
"<title>HTML Rendered by Servlet</title>" +
"</head>" +
"<body>" +
"<h1>HTML Rendered by Servlet</h1></br>" +
"<p>This page was rendered by the ExampleOne Servlet!</p>" +
"</body>" +
"</html>"
);
}
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<!DOCTYPE html><html>" + "<head>" + "<meta charset=\"UTF-8\" />" + "<title>HTML Rendered by Servlet</title>" + "</head>" + "<body>" + "<h1>HTML Rendered by Servlet</h1></br>" + "<p>This page was rendered by the ExampleOne Servlet!</p>"
+ "</body>" + "</html>");
}
}

View File

@ -7,18 +7,14 @@ import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet(
name = "ExampleThree",
description = "JSP Servlet With Annotations",
urlPatterns = {"/ExampleThree"}
)
@WebServlet(name = "ExampleThree", description = "JSP Servlet With Annotations", urlPatterns = { "/ExampleThree" })
public class ExampleThree extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String message = request.getParameter("message");
request.setAttribute("text", message);
request.getRequestDispatcher("/jsp/ExampleThree.jsp").forward(request, response);
}
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String message = request.getParameter("message");
request.setAttribute("text", message);
request.getRequestDispatcher("/jsp/ExampleThree.jsp").forward(request, response);
}
}

View File

@ -9,7 +9,7 @@ import org.springframework.web.servlet.ModelAndView;
@Controller
public class ErrorController {
@RequestMapping(value = "500Error", method = RequestMethod.GET)
public void throwRuntimeException() {
throw new NullPointerException("Throwing a null pointer exception");
@ -34,19 +34,18 @@ public class ErrorController {
errorMsg = "Http Error Code : 404. Resource not found";
break;
}
// Handle other 4xx error codes.
// Handle other 4xx error codes.
case 500: {
errorMsg = "Http Error Code : 500. Internal Server Error";
break;
}
// Handle other 5xx error codes.
// Handle other 5xx error codes.
}
errorPage.addObject("errorMsg", errorMsg);
return errorPage;
}
private int getErrorCode(HttpServletRequest httpRequest) {
return (Integer) httpRequest
.getAttribute("javax.servlet.error.status_code");
return (Integer) httpRequest.getAttribute("javax.servlet.error.status_code");
}
}

View File

@ -14,15 +14,15 @@ import com.baeldung.spring.service.RawDBDemoGeoIPLocationService;
@Controller
public class GeoIPTestController {
private RawDBDemoGeoIPLocationService locationService;
public GeoIPTestController() throws IOException {
locationService
= new RawDBDemoGeoIPLocationService();
locationService = new RawDBDemoGeoIPLocationService();
}
@RequestMapping(value="/GeoIPTest", method = RequestMethod.POST)
@RequestMapping(value = "/GeoIPTest", method = RequestMethod.POST)
@ResponseBody
public GeoIP getLocation(
@RequestParam(value="ipAddress", required=true) String ipAddress) throws Exception {
public GeoIP getLocation(@RequestParam(value = "ipAddress", required = true) String ipAddress) throws Exception {
return locationService.getLocation(ipAddress);
}
}

View File

@ -12,7 +12,6 @@ import org.springframework.web.context.support.ServletContextResource;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletResponse;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

View File

@ -5,15 +5,15 @@ public class GeoIP {
private String city;
private String latitude;
private String longitude;
public GeoIP() {
}
public GeoIP(String ipAddress) {
this.ipAddress = ipAddress;
}
public GeoIP(String ipAddress, String city, String latitude, String longitude) {
this.ipAddress = ipAddress;
this.city = city;
@ -52,5 +52,5 @@ public class GeoIP {
public void setLongitude(String longitude) {
this.longitude = longitude;
}
}

View File

@ -9,18 +9,18 @@ import com.maxmind.geoip2.DatabaseReader;
import com.maxmind.geoip2.exception.GeoIp2Exception;
import com.maxmind.geoip2.model.CityResponse;
public class RawDBDemoGeoIPLocationService{
public class RawDBDemoGeoIPLocationService {
private DatabaseReader dbReader;
public RawDBDemoGeoIPLocationService() throws IOException {
File database = new File("your-path-to-db-file");
dbReader = new DatabaseReader.Builder(database).build();
}
public GeoIP getLocation(String ip) throws IOException, GeoIp2Exception {
InetAddress ipAddress = InetAddress.getByName(ip);
CityResponse response = dbReader.city(ipAddress);
String cityName = response.getCity().getName();
String latitude = response.getLocation().getLatitude().toString();
String longitude = response.getLocation().getLongitude().toString();

View File

@ -1,10 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
xsi:schemaLocation="
http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1"
>
<display-name>Spring MVC XML Application</display-name>
<!-- Spring root -->
@ -65,4 +64,4 @@
<error-page>
<location>/errors</location>
</error-page>
</web-app>
</web-app>

View File

@ -10,22 +10,21 @@ import com.maxmind.geoip2.DatabaseReader;
import com.maxmind.geoip2.exception.GeoIp2Exception;
import com.maxmind.geoip2.model.CityResponse;
public class GeoIpIntegrationTest {
@Test
public void givenIP_whenFetchingCity_thenReturnsCityData() throws IOException, GeoIp2Exception {
File database = new File("your-path-to-db-file");
DatabaseReader dbReader = new DatabaseReader.Builder(database).build();
InetAddress ipAddress = InetAddress.getByName("your-public-ip");
CityResponse response = dbReader.city(ipAddress);
String countryName = response.getCountry().getName();
String cityName = response.getCity().getName();
String postal = response.getPostal().getCode();
String state = response.getLeastSpecificSubdivision().getName();
}
}

View File

@ -0,0 +1,92 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-reactive-websocket</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>spring-reactive-websocket</name>
<description>Reactive WebSockets with Spring 5</description>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-integration</artifactId>
<version>2.0.0.M7</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<version>2.0.0.M7</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>compile</scope>
<version>RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</project>

View File

@ -0,0 +1,11 @@
package com.baeldung;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class Event {
private String eventId;
private String eventDt;
}

View File

@ -0,0 +1,38 @@
package com.baeldung;
import java.net.URI;
import java.time.Duration;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.reactive.socket.WebSocketMessage;
import org.springframework.web.reactive.socket.client.ReactorNettyWebSocketClient;
import org.springframework.web.reactive.socket.client.WebSocketClient;
import reactor.core.publisher.Mono;
@SpringBootApplication
public class ReactiveWebSocketApplication {
public static void main(String[] args) {
SpringApplication.run(ReactiveWebSocketApplication.class, args);
}
/**
* Spring Reactive WebSocket Client
* **/
@Bean
CommandLineRunner runner() {
return run -> {
WebSocketClient client = new ReactorNettyWebSocketClient();
client.execute(URI.create("ws://localhost:8080/event-emitter"), session -> session.send(Mono.just(session.textMessage("event-me-from-spring-reactive-client")))
.thenMany(session.receive()
.map(WebSocketMessage::getPayloadAsText)
.log())
.then())
.block();
// .block(Duration.ofSeconds(10L));//force timeout after given duration
};
}
}

View File

@ -0,0 +1,34 @@
package com.baeldung;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.HandlerMapping;
import org.springframework.web.reactive.handler.SimpleUrlHandlerMapping;
import org.springframework.web.reactive.socket.WebSocketHandler;
import org.springframework.web.reactive.socket.server.support.WebSocketHandlerAdapter;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class ReactiveWebSocketConfiguration {
@Autowired
private WebSocketHandler webSocketHandler;
@Bean
public HandlerMapping webSocketHandlerMapping() {
Map<String, WebSocketHandler> map = new HashMap<>();
map.put("/event-emitter", webSocketHandler);
SimpleUrlHandlerMapping handlerMapping = new SimpleUrlHandlerMapping();
handlerMapping.setOrder(1);
handlerMapping.setUrlMap(map);
return handlerMapping;
}
@Bean
public WebSocketHandlerAdapter handlerAdapter() {
return new WebSocketHandlerAdapter();
}
}

View File

@ -0,0 +1,71 @@
package com.baeldung;
import org.springframework.web.reactive.socket.WebSocketSession;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.socket.WebSocketHandler;
import org.springframework.web.reactive.socket.WebSocketMessage;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import javax.annotation.PostConstruct;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.UUID;
@Component
public class ReactiveWebSocketHandler implements WebSocketHandler {
private Flux<Event> eventFlux;
private Flux<Event> intervalFlux;
/**
* Here we prepare a Flux that will emit a message every second
*/
@PostConstruct
private void init() throws InterruptedException {
eventFlux = Flux.generate(e -> {
Event event = new Event(UUID.randomUUID()
.toString(),
LocalDateTime.now()
.toString());
e.next(event);
});
intervalFlux = Flux.interval(Duration.ofMillis(1000L))
.zipWith(eventFlux, (time, event) -> event);
}
/**
* On each new client session, send the message flux to the client.
* Spring subscribes to the flux and send every new flux event to the WebSocketSession object
* @param session
* @return Mono<Void>
*/
@Override
public Mono<Void> handle(WebSocketSession webSocketSession) {
ObjectMapper json = new ObjectMapper();
return webSocketSession.send(intervalFlux.map(event -> {
try {
String jsonEvent = json.writeValueAsString(event);
System.out.println(jsonEvent);
return jsonEvent;
} catch (JsonProcessingException e) {
e.printStackTrace();
return "";
}
})
.map(webSocketSession::textMessage))
.and(webSocketSession.receive()
.map(WebSocketMessage::getPayloadAsText)
.log());
}
}

View File

@ -0,0 +1,34 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Baeldung: Spring 5 Reactive Client WebSocket (Browser)</title>
</head>
<body>
<div class="events"></div>
<script>
var clientWebSocket = new WebSocket("ws://localhost:8080/event-emitter");
clientWebSocket.onopen = function() {
console.log("clientWebSocket.onopen", clientWebSocket);
console.log("clientWebSocket.readyState", "websocketstatus");
clientWebSocket.send("event-me-from-browser");
}
clientWebSocket.onclose = function(error) {
console.log("clientWebSocket.onclose", clientWebSocket, error);
events("Closing connection");
}
clientWebSocket.onerror = function(error) {
console.log("clientWebSocket.onerror", clientWebSocket, error);
events("An error occured");
}
clientWebSocket.onmessage = function(error) {
console.log("clientWebSocket.onmessage", clientWebSocket, error);
events(error.data);
}
function events(responseEvent) {
document.querySelector(".events").innerHTML += responseEvent + "<br>";
}
</script>
</body>
</html>

View File

@ -0,0 +1,14 @@
package org.baeldung.methodsecurity.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.security.access.prepost.PreAuthorize;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@PreAuthorize("hasRole('VIEWER')")
public @interface IsViewer {
}

View File

@ -1,11 +1,11 @@
package org.baeldung.testmethodsecurity.config;
package org.baeldung.methodsecurity.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration;
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
}

View File

@ -1,4 +1,4 @@
package org.baeldung.testmethodsecurity.entity;
package org.baeldung.methodsecurity.entity;
import java.util.Collection;
@ -6,15 +6,15 @@ import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
@SuppressWarnings("serial")
public class CustomUser extends User{
public class CustomUser extends User {
private String nickName;
public CustomUser(String username, String password, Collection<? extends GrantedAuthority> authorities) {
super(username, password, authorities);
}
public CustomUser(String username, String password, Collection<? extends GrantedAuthority> authorities,String nickName) {
public CustomUser(String username, String password, Collection<? extends GrantedAuthority> authorities, String nickName) {
super(username, password, authorities);
this.nickName = nickName;
}

View File

@ -0,0 +1,57 @@
package org.baeldung.methodsecurity.repository;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.baeldung.methodsecurity.entity.CustomUser;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
@Service
public class UserRoleRepository {
static Map<String, CustomUser> DB_BASED_USER_MAPPING;
static {
DB_BASED_USER_MAPPING = new LinkedHashMap<>();
DB_BASED_USER_MAPPING.put("jane", new CustomUser("jane", "1234", getGrantedAuthorities("ROLE_USER", "ROLE_VIEWER"), "jane"));
DB_BASED_USER_MAPPING.put("john", new CustomUser("john", "1234", getGrantedAuthorities("ROLE_EDITOR", "ROLE_ADMIN"), "jane"));
DB_BASED_USER_MAPPING.put("jack", new CustomUser("jack", "1234", getGrantedAuthorities("ROLE_USER", "ROLE_REVIEWER"), "jane"));
}
private static List<GrantedAuthority> getGrantedAuthorities(String... roles) {
ArrayList<GrantedAuthority> authorities = new ArrayList<>();
for (String role : roles) {
authorities.add(new SimpleGrantedAuthority(role));
}
return authorities;
}
public CustomUser loadUserByUserName(String username) {
if (DB_BASED_USER_MAPPING.containsKey(username)) {
return DB_BASED_USER_MAPPING.get(username);
}
throw new UsernameNotFoundException("User " + username + " cannot be found");
}
public boolean isValidUsername(String username) {
return DB_BASED_USER_MAPPING.containsKey(username);
}
public boolean isValidRole(String roleName) {
return roleName.startsWith("ROLE_");
}
public List<String> getAllUsernames() {
List<String> usernames = new ArrayList<>();
usernames.add("jane");
usernames.add("john");
usernames.add("jack");
return usernames;
}
}

View File

@ -1,6 +1,6 @@
package org.baeldung.testmethodsecurity.service;
package org.baeldung.methodsecurity.service;
import org.baeldung.testmethodsecurity.repository.UserRoleRepository;
import org.baeldung.methodsecurity.repository.UserRoleRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;

View File

@ -0,0 +1,18 @@
package org.baeldung.methodsecurity.service;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;
@Service
@PreAuthorize("hasRole('ROLE_ADMIN')")
public class SystemService {
public String getSystemYear(){
return "2017";
}
public String getSystemDate(){
return "31-12-2017";
}
}

View File

@ -0,0 +1,108 @@
package org.baeldung.methodsecurity.service;
import java.util.List;
import java.util.stream.Collectors;
import javax.annotation.security.RolesAllowed;
import org.baeldung.methodsecurity.annotation.IsViewer;
import org.baeldung.methodsecurity.entity.CustomUser;
import org.baeldung.methodsecurity.repository.UserRoleRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.annotation.Secured;
import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.security.access.prepost.PostFilter;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.access.prepost.PreFilter;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
@Service
public class UserRoleService {
@Autowired
UserRoleRepository userRoleRepository;
@Secured("ROLE_VIEWER")
public String getUsername() {
SecurityContext securityContext = SecurityContextHolder.getContext();
return securityContext.getAuthentication().getName();
}
@Secured({ "ROLE_VIEWER", "ROLE_EDITOR" })
public boolean isValidUsername(String username) {
return userRoleRepository.isValidUsername(username);
}
@RolesAllowed("ROLE_VIEWER")
public String getUsername2() {
SecurityContext securityContext = SecurityContextHolder.getContext();
return securityContext.getAuthentication().getName();
}
@RolesAllowed({ "ROLE_VIEWER", "ROLE_EDITOR" })
public boolean isValidUsername2(String username) {
return userRoleRepository.isValidUsername(username);
}
@PreAuthorize("hasRole('ROLE_VIEWER')")
public String getUsernameInUpperCase() {
return getUsername().toUpperCase();
}
@PreAuthorize("hasAuthority('SYS_ADMIN')")
public String getUsernameLC() {
return getUsername().toLowerCase();
}
@PreAuthorize("hasRole('ROLE_VIEWER') or hasRole('ROLE_EDITOR')")
public boolean isValidUsername3(String username) {
return userRoleRepository.isValidUsername(username);
}
@PreAuthorize("#username == authentication.principal.username")
public String getMyRoles(String username) {
SecurityContext securityContext = SecurityContextHolder.getContext();
return securityContext.getAuthentication().getAuthorities().stream().map(auth -> auth.getAuthority()).collect(Collectors.joining(","));
}
@PostAuthorize("#username == authentication.principal.username")
public String getMyRoles2(String username) {
SecurityContext securityContext = SecurityContextHolder.getContext();
return securityContext.getAuthentication().getAuthorities().stream().map(auth -> auth.getAuthority()).collect(Collectors.joining(","));
}
@PostAuthorize("returnObject.username == authentication.principal.nickName")
public CustomUser loadUserDetail(String username) {
return userRoleRepository.loadUserByUserName(username);
}
@PreFilter("filterObject != authentication.principal.username")
public String joinUsernames(List<String> usernames) {
return usernames.stream().collect(Collectors.joining(";"));
}
@PreFilter(value = "filterObject != authentication.principal.username", filterTarget = "usernames")
public String joinUsernamesAndRoles(List<String> usernames, List<String> roles) {
return usernames.stream().collect(Collectors.joining(";")) + ":" + roles.stream().collect(Collectors.joining(";"));
}
@PostFilter("filterObject != authentication.principal.username")
public List<String> getAllUsernamesExceptCurrent() {
return userRoleRepository.getAllUsernames();
}
@IsViewer
public String getUsername4() {
SecurityContext securityContext = SecurityContextHolder.getContext();
return securityContext.getAuthentication().getName();
}
@PreAuthorize("#username == authentication.principal.username")
@PostAuthorize("returnObject.username == authentication.principal.nickName")
public CustomUser securedLoadUserDetail(String username) {
return userRoleRepository.loadUserByUserName(username);
}
}

View File

@ -1,41 +0,0 @@
package org.baeldung.testmethodsecurity.repository;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.baeldung.testmethodsecurity.entity.CustomUser;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
@Service
public class UserRoleRepository {
static Map<String,CustomUser> DB_BASED_USER_MAPPING;
static{
DB_BASED_USER_MAPPING = new LinkedHashMap<>();
DB_BASED_USER_MAPPING.put("jane", new CustomUser("jane","1234", getGrantedAuthorities("ROLE_USER","ROLE_VIEWER"),"jane"));
DB_BASED_USER_MAPPING.put("john", new CustomUser("john","1234", getGrantedAuthorities("ROLE_EDITOR","ROLE_ADMIN"),"jane"));
DB_BASED_USER_MAPPING.put("jack", new CustomUser("jack","1234", getGrantedAuthorities("ROLE_USER","ROLE_REVIEWER"),"jane"));
}
private static List<GrantedAuthority> getGrantedAuthorities(String...roles){
ArrayList<GrantedAuthority> authorities = new ArrayList<>();
for (String role : roles){
authorities.add(new SimpleGrantedAuthority(role));
}
return authorities;
}
public CustomUser loadUserByUserName(String username){
if (DB_BASED_USER_MAPPING.containsKey(username)){
return DB_BASED_USER_MAPPING.get(username);
}
throw new UsernameNotFoundException("User "+username+" cannot be found");
}
}

View File

@ -1,29 +0,0 @@
package org.baeldung.testmethodsecurity.service;
import org.baeldung.testmethodsecurity.entity.CustomUser;
import org.baeldung.testmethodsecurity.repository.UserRoleRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
@Service
public class UserRoleService {
@Autowired
UserRoleRepository userRoleRepository;
@PreAuthorize("hasRole('ROLE_VIEWER') or hasAuthority('SYS_ADMIN')")
public String getUsername(){
SecurityContext securityContext = SecurityContextHolder.getContext();
return securityContext.getAuthentication().getName();
}
@PostAuthorize("returnObject.username == authentication.principal.nickName")
public CustomUser loadUserDetail(String username){
return userRoleRepository.loadUserByUserName(username);
}
}

View File

@ -0,0 +1,49 @@
package org.baeldung.methodsecurity;
import static org.junit.Assert.*;
import org.baeldung.methodsecurity.service.SystemService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@ContextConfiguration
public class TestClassLevelSecurity {
@Autowired
SystemService systemService;
@Configuration
@ComponentScan("org.baeldung.methodsecurity.*")
public static class SpringConfig {
}
@Test
@WithMockUser(username="john",roles={"ADMIN"})
public void givenRoleAdmin_whenCallGetSystemYear_return2017(){
String systemYear = systemService.getSystemYear();
assertEquals("2017",systemYear);
}
@Test(expected=AccessDeniedException.class)
@WithMockUser(username="john",roles={"VIEWER"})
public void givenRoleViewer_whenCallGetSystemYear_returnAccessDenied(){
String systemYear = systemService.getSystemYear();
assertEquals("2017",systemYear);
}
@Test
@WithMockUser(username="john",roles={"ADMIN"})
public void givenRoleAdmin_whenCallGetSystemDate_returnDate(){
String systemYear = systemService.getSystemDate();
assertEquals("31-12-2017",systemYear);
}
}

View File

@ -0,0 +1,176 @@
package org.baeldung.methodsecurity;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.List;
import org.baeldung.methodsecurity.service.UserRoleService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
import org.springframework.security.test.context.support.WithAnonymousUser;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@ContextConfiguration
public class TestMethodSecurity {
@Autowired
UserRoleService userRoleService;
@Configuration
@ComponentScan("org.baeldung.methodsecurity.*")
public static class SpringConfig {
}
@Test(expected = AuthenticationCredentialsNotFoundException.class)
public void givenNoSecurity_whenCallGetUsername_thenReturnException() {
String userName = userRoleService.getUsername();
assertEquals("john", userName);
}
@Test
@WithMockUser(username = "john", roles = { "VIEWER" })
public void givenRoleViewer_whenCallGetUsername_thenReturnUsername() {
String userName = userRoleService.getUsername();
assertEquals("john", userName);
}
@Test
@WithMockUser(username = "john", roles = { "EDITOR" })
public void givenUsernameJohn_whenCallIsValidUsername_thenReturnTrue() {
boolean isValid = userRoleService.isValidUsername("john");
assertEquals(true, isValid);
}
@Test(expected = AccessDeniedException.class)
@WithMockUser(username = "john", roles = { "ADMIN" })
public void givenRoleAdmin_whenCallGetUsername_thenReturnAccessDenied() {
userRoleService.getUsername();
}
@Test(expected = AccessDeniedException.class)
@WithMockUser(username = "john", roles = { "USER" })
public void givenRoleUser_whenCallGetUsername2_thenReturnAccessDenied() {
userRoleService.getUsername2();
}
@Test
@WithMockUser(username = "john", roles = { "VIEWER", "EDITOR" })
public void givenRoleViewer_whenCallGetUsername2_thenReturnUsername() {
String userName = userRoleService.getUsername2();
assertEquals("john", userName);
}
@Test
@WithMockUser(username = "john", roles = { "VIEWER" })
public void givenUsernameJerry_whenCallIsValidUsername2_thenReturnFalse() {
boolean isValid = userRoleService.isValidUsername2("jerry");
assertEquals(false, isValid);
}
@Test
@WithMockUser(username = "JOHN", authorities = { "SYS_ADMIN" })
public void givenAuthoritySysAdmin_whenCallGetUsernameInLowerCase_thenReturnUsername() {
String username = userRoleService.getUsernameLC();
assertEquals("john", username);
}
@Test
@WithMockUser(username = "john", roles = { "ADMIN", "USER", "VIEWER" })
public void givenUserJohn_whenCallGetMyRolesWithJohn_thenReturnRoles() {
String roles = userRoleService.getMyRoles("john");
assertEquals("ROLE_ADMIN,ROLE_USER,ROLE_VIEWER", roles);
}
@Test(expected = AccessDeniedException.class)
@WithMockUser(username = "john", roles = { "ADMIN", "USER", "VIEWER" })
public void givenUserJane_whenCallGetMyRolesWithJane_thenAccessDenied() {
userRoleService.getMyRoles("jane");
}
@Test
@WithMockUser(username = "john", roles = { "ADMIN", "USER", "VIEWER" })
public void givenUserJohn_whenCallGetMyRoles2WithJohn_thenReturnRoles() {
String roles = userRoleService.getMyRoles2("john");
assertEquals("ROLE_ADMIN,ROLE_USER,ROLE_VIEWER", roles);
}
@Test(expected = AccessDeniedException.class)
@WithMockUser(username = "john", roles = { "ADMIN", "USER", "VIEWER" })
public void givenUserJane_whenCallGetMyRoles2WithJane_thenAccessDenied() {
userRoleService.getMyRoles2("jane");
}
@Test(expected = AccessDeniedException.class)
@WithAnonymousUser
public void givenAnomynousUser_whenCallGetUsername_thenAccessDenied() {
userRoleService.getUsername();
}
@Test
@WithMockJohnViewer
public void givenMockedJohnViewer_whenCallGetUsername_thenReturnUsername() {
String userName = userRoleService.getUsername();
assertEquals("john", userName);
}
@Test
@WithMockUser(username = "jane")
public void givenListContainCurrentUsername_whenJoinUsernames_thenReturnUsernames() {
List<String> usernames = new ArrayList<>();
usernames.add("jane");
usernames.add("john");
usernames.add("jack");
String containCurrentUser = userRoleService.joinUsernames(usernames);
assertEquals("john;jack", containCurrentUser);
}
@Test
@WithMockUser(username = "john")
public void givenListContainCurrentUsername_whenCallJoinUsernamesAndRoles_thenReturnUsernameAndRoles() {
List<String> usernames = new ArrayList<>();
usernames.add("jane");
usernames.add("john");
usernames.add("jack");
List<String> roles = new ArrayList<>();
roles.add("ROLE_ADMIN");
roles.add("ROLE_TEST");
String containCurrentUser = userRoleService.joinUsernamesAndRoles(usernames, roles);
assertEquals("jane;jack:ROLE_ADMIN;ROLE_TEST", containCurrentUser);
}
@Test
@WithMockUser(username = "john")
public void givenUserJohn_whenCallGetAllUsernamesExceptCurrent_thenReturnOtherusernames() {
List<String> others = userRoleService.getAllUsernamesExceptCurrent();
assertEquals(2, others.size());
assertTrue(others.contains("jane"));
assertTrue(others.contains("jack"));
}
@Test
@WithMockUser(username = "john", roles = { "VIEWER" })
public void givenRoleViewer_whenCallGetUsername4_thenReturnUsername() {
String userName = userRoleService.getUsername4();
assertEquals("john", userName);
}
@Test(expected = AccessDeniedException.class)
@WithMockUser(username = "john")
public void givenDefaultRole_whenCallGetUsername4_thenAccessDenied() {
userRoleService.getUsername4();
}
}

View File

@ -1,8 +1,8 @@
package org.baeldung.testmethodsecurity;
package org.baeldung.methodsecurity;
import static org.junit.Assert.assertEquals;
import org.baeldung.testmethodsecurity.service.UserRoleService;
import org.baeldung.methodsecurity.service.UserRoleService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
@ -14,20 +14,20 @@ import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@ContextConfiguration
@WithMockUser(username="john",roles={"VIEWER"})
@WithMockUser(username = "john", roles = { "VIEWER" })
public class TestWithMockUserAtClassLevel {
@Test
public void givenRoleViewer_whenCallGetUsername_thenReturnUsername(){
public void givenRoleViewer_whenCallGetUsername_thenReturnUsername() {
String currentUserName = userService.getUsername();
assertEquals("john",currentUserName);
assertEquals("john", currentUserName);
}
@Autowired
UserRoleService userService;
@Configuration
@ComponentScan("org.baeldung.testmethodsecurity.*")
@ComponentScan("org.baeldung.methodsecurity.*")
public static class SpringConfig {
}

View File

@ -0,0 +1,56 @@
package org.baeldung.methodsecurity;
import static org.junit.Assert.assertEquals;
import org.baeldung.methodsecurity.entity.CustomUser;
import org.baeldung.methodsecurity.service.UserRoleService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.test.context.support.WithUserDetails;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@ContextConfiguration
public class TestWithUserDetails {
@Autowired
UserRoleService userService;
@Configuration
@ComponentScan("org.baeldung.methodsecurity.*")
public static class SpringConfig {
}
@Test
@WithUserDetails(value = "john", userDetailsServiceBeanName = "userDetailService")
public void whenJohn_callLoadUserDetail_thenOK() {
CustomUser user = userService.loadUserDetail("jane");
assertEquals("jane", user.getNickName());
}
@Test
@WithUserDetails(value = "jane", userDetailsServiceBeanName = "userDetailService")
public void givenJane_callSecuredLoadUserDetailWithJane_thenOK() {
CustomUser user = userService.securedLoadUserDetail("jane");
assertEquals("jane", user.getNickName());
assertEquals("jane", user.getUsername());
}
@Test(expected = AccessDeniedException.class)
@WithUserDetails(value = "john", userDetailsServiceBeanName = "userDetailService")
public void givenJohn_callSecuredLoadUserDetailWithJane_thenAccessDenied() {
userService.securedLoadUserDetail("jane");
}
@Test(expected = AccessDeniedException.class)
@WithUserDetails(value = "john", userDetailsServiceBeanName = "userDetailService")
public void givenJohn_callSecuredLoadUserDetailWithJohn_thenAccessDenied() {
userService.securedLoadUserDetail("john");
}
}

View File

@ -1,4 +1,4 @@
package org.baeldung.testmethodsecurity;
package org.baeldung.methodsecurity;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

View File

@ -1,57 +0,0 @@
package org.baeldung.testmethodsecurity;
import static org.junit.Assert.assertEquals;
import org.baeldung.testmethodsecurity.service.UserRoleService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.test.context.support.WithAnonymousUser;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@ContextConfiguration
public class TestMethodSecurity{
@Autowired
UserRoleService userRoleService;
@Configuration
@ComponentScan("org.baeldung.testmethodsecurity.*")
public static class SpringConfig {
}
@Test
@WithMockUser(username="john",roles={"VIEWER"})
public void givenRoleViewer_whenCallGetUsername_thenReturnUsername(){
String userName = userRoleService.getUsername();
assertEquals("john", userName);
}
@Test
@WithMockUser(username="john",authorities={"SYS_ADMIN"})
public void givenAuthoritySysAdmin_whenCallGetUsername_thenReturnUsername(){
String userName = userRoleService.getUsername();
assertEquals("john", userName);
}
@Test(expected=AccessDeniedException.class)
@WithAnonymousUser
public void givenAnomynousUser_whenCallGetUsername_thenAccessDenied(){
userRoleService.getUsername();
}
@Test
@WithMockJohnViewer
public void givenMockedJohnViewer_whenCallGetUsername_thenReturnUsername(){
String userName = userRoleService.getUsername();
assertEquals("john", userName);
}
}

View File

@ -1,35 +0,0 @@
package org.baeldung.testmethodsecurity;
import static org.junit.Assert.assertEquals;
import org.baeldung.testmethodsecurity.entity.CustomUser;
import org.baeldung.testmethodsecurity.service.UserRoleService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.test.context.support.WithUserDetails;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@ContextConfiguration
public class TestWithUserDetails {
@Autowired
UserRoleService userService;
@Configuration
@ComponentScan("org.baeldung.testmethodsecurity.*")
public static class SpringConfig {
}
@Test
@WithUserDetails(value="john",userDetailsServiceBeanName="userDetailService")
public void whenJohn_callLoadUserDetail_thenOK(){
CustomUser user = userService.loadUserDetail("jane");
assertEquals("jane",user.getNickName());
}
}

View File

@ -0,0 +1,43 @@
package org.baeldung.web.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
@RequestMapping(value = "/custom")
public class LoginController {
@Autowired
private AuthenticationManager authManager;
public LoginController() {
super();
}
// API
// custom login
@RequestMapping(value = "/login", method = RequestMethod.POST)
public void login(@RequestParam("username") final String username, @RequestParam("password") final String password, final HttpServletRequest request) {
UsernamePasswordAuthenticationToken authReq =
new UsernamePasswordAuthenticationToken(username, password);
Authentication auth = authManager.authenticate(authReq);
SecurityContext sc = SecurityContextHolder.getContext();
sc.setAuthentication(auth);
HttpSession session = request.getSession(true);
session.setAttribute("SPRING_SECURITY_CONTEXT", sc);
}
}

View File

@ -0,0 +1,27 @@
package org.baeldung.web.controller;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
@RequestMapping(value = "/custom")
public class PrintUserController {
public PrintUserController() {
super();
}
// API
// print user
@RequestMapping(value = "/print", method = RequestMethod.GET)
public void printUser() {
SecurityContext sc = SecurityContextHolder.getContext();
System.out.println("Logged User: "+sc.getAuthentication().getName());
}
}

View File

@ -0,0 +1,58 @@
package org.baeldung.security.spring;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.BeanIds;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class ManualSecurityConfig extends WebSecurityConfigurerAdapter {
public ManualSecurityConfig() {
super();
}
// java config
@Override
protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("user1").password("user1Pass").authorities("ROLE_USER").and().withUser("admin").password("adminPass").authorities("ROLE_ADMIN");
}
@Override
public void configure(final WebSecurity web) throws Exception {
web.ignoring().antMatchers("/resources/**");
}
@Bean(name = BeanIds.AUTHENTICATION_MANAGER)
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(final HttpSecurity http) throws Exception {
// @formatter:off
http
.authorizeRequests()
.mvcMatchers("/custom/login").permitAll()
.anyRequest().authenticated()
.and()
.httpBasic()
.and()
.headers().cacheControl().disable()
.and()
.csrf().disable()
;
// @formatter:on
}
}

View File

@ -0,0 +1,58 @@
package org.baeldung.security.spring;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import javax.servlet.http.HttpSession;
import org.baeldung.spring.MvcConfig;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.MockHttpSession;
import org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(classes = { MvcConfig.class, ManualSecurityConfig.class })
public class ManualSecurityIntegrationTest {
@Autowired
WebApplicationContext wac;
private MockMvc mockMvc;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
mockMvc = MockMvcBuilders.webAppContextSetup(wac).apply(SecurityMockMvcConfigurers.springSecurity()).build();
}
/**
* Execute custom login and access the endpoint
*/
@Test
public void whenLoginIsSuccessFulThenEndpointCanBeAccessedAndCurrentUserPrinted() throws Exception {
mockMvc.perform(get("/custom/print"))
.andExpect(status().isUnauthorized());
HttpSession session = mockMvc.perform(post("/custom/login").param("username", "user1").param("password", "user1Pass"))
.andExpect(status().isOk())
.andReturn()
.getRequest()
.getSession();
mockMvc.perform(get("/custom/print").session((MockHttpSession) session))
.andExpect(status().is2xxSuccessful());
}
}