Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Alessio Stalla 2018-01-18 12:55:16 +01:00
commit 407607131f
108 changed files with 2405 additions and 186 deletions

View File

@ -1,3 +1,4 @@
### Relevant Articles:
- [Microsoft Word Processing in Java with Apache POI](http://www.baeldung.com/java-microsoft-word-with-apache-poi)
- [Working with Microsoft Excel in Java](http://www.baeldung.com/java-microsoft-excel)
- [Creating a MS PowerPoint Presentation in Java](https://github.com/eugenp/tutorials/tree/master/apache-poi)

View File

@ -37,3 +37,6 @@
- [Iterable to Stream in Java](http://www.baeldung.com/java-iterable-to-stream)
- [Converting String to Stream of chars](http://www.baeldung.com/java-string-to-stream)
- [How to Iterate Over a Stream With Indices](http://www.baeldung.com/java-stream-indices)
- [Efficient Word Frequency Calculator in Java](http://www.baeldung.com/java-word-frequency)
- [Primitive Type Streams in Java 8](http://www.baeldung.com/java-8-primitive-streams)
- [Fail-Safe Iterator vs Fail-Fast Iterator](http://www.baeldung.com/java-fail-safe-vs-fail-fast-iterator)

View File

@ -33,3 +33,4 @@
- [Daemon Threads in Java](http://www.baeldung.com/java-daemon-thread)
- [Implementing a Runnable vs Extending a Thread](http://www.baeldung.com/java-runnable-vs-extending-thread)
- [How to Kill a Java Thread](http://www.baeldung.com/java-thread-stop)
- [How to Wait for Threads to Finish in the ExecutorService](http://www.baeldung.com/java-executor-wait-for-threads)

View File

@ -118,3 +118,11 @@
- [Implementing a Binary Tree in Java](http://www.baeldung.com/java-binary-tree)
- [A Guide to ThreadLocalRandom in Java](http://www.baeldung.com/java-thread-local-random)
- [RegEx for matching Date Pattern in Java](http://www.baeldung.com/java-date-regular-expressions)
- [Introduction to the JDBC RowSet Interface in Java](http://www.baeldung.com/java-jdbc-rowset)
- [Nested Classes in Java](http://www.baeldung.com/java-nested-classes)
- [A Guide to Java Loops](http://www.baeldung.com/java-loops)
- [Varargs in Java](http://www.baeldung.com/java-varargs)
- [A Guide to HashSet in Java](http://www.baeldung.com/java-hashset)
- [A Guide to Inner Interfaces in Java](http://www.baeldung.com/java-inner-interfaces)
- [Polymorphism in Java](http://www.baeldung.com/java-polymorphism)
- [Recursion In Java](http://www.baeldung.com/java-recursion)

View File

@ -16,5 +16,5 @@
- [Delegated Properties in Kotlin](http://www.baeldung.com/kotlin-delegated-properties)
- [Sealed Classes in Kotlin](http://www.baeldung.com/kotlin-sealed-classes)
- [JUnit 5 for Kotlin Developers](http://www.baeldung.com/junit-5-kotlin)
- [Extension Methods in Kotlin](http://www.baeldung.com/kotlin-extension-methods)

View File

@ -1,4 +1,4 @@
## Relevant articles:
- [Intro to Dubbo](http://www.baeldung.com/dubbo-intro)
- [Introduction to Dubbo](http://www.baeldung.com/dubbo)

View File

@ -1,2 +1,3 @@
### Relevant Articles:
- [Database Migrations with Flyway](http://www.baeldung.com/database-migrations-with-flyway)
- [A Guide to Flyway Callbacks](http://www.baeldung.com/flyway-callbacks)

View File

@ -1,2 +1,4 @@
## Relevant articles:
- [Introduction to Gradle](http://www.baeldung.com/gradle)
- [Writing Custom Gradle Plugins](http://www.baeldung.com/gradle-create-plugin)
- [Creating a Fat Jar in Gradle](http://www.baeldung.com/gradle-fat-jar)

15
guest/deep-jsf/README.md Normal file
View File

@ -0,0 +1,15 @@
## Building
To build the module, use Maven's `package` goal:
```
mvn clean package
```
The `war` file will be available at `target/deep-jsf.war`
## Running
The `war` application is deployed to a Java EE 7 compliant application server, for example, to GlassFish 4 or later.
The example then will be accessible at http://localhost:8080/deep-jsf/index.xhtml

40
guest/deep-jsf/pom.xml Normal file
View File

@ -0,0 +1,40 @@
<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>
<groupId>com.stackify</groupId>
<artifactId>deep-jsf</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<failOnMissingWebXml>false</failOnMissingWebXml>
</properties>
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>deep-jsf</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,14 @@
package com.stackify.deepjsf;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
@ManagedBean
@RequestScoped
public class GreetControllerBean {
public String greet() {
return "greet";
}
}

View File

@ -0,0 +1,47 @@
package com.stackify.deepjsf;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.component.UIComponent;
import javax.faces.component.UIViewRoot;
import javax.faces.component.visit.VisitContext;
import javax.faces.component.visit.VisitResult;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.servlet.http.HttpServletRequest;
@ManagedBean
@RequestScoped
public class PhaseListenerBean {
public void beforeListener(PhaseEvent event) {
if (!event.getPhaseId().equals(PhaseId.RENDER_RESPONSE)) {
return;
}
UIViewRoot root = event.getFacesContext().getViewRoot();
boolean showNewFeature = showNewFeatureForIp(event);
processComponentTree(root, event, showNewFeature);
}
private boolean showNewFeatureForIp(PhaseEvent event) {
HttpServletRequest request = (HttpServletRequest) event.getFacesContext()
.getExternalContext().getRequest();
String ip = request.getRemoteAddr();
return !ip.startsWith("127.0");
}
private void processComponentTree(UIComponent component, PhaseEvent event, boolean show) {
component.visitTree(VisitContext.createVisitContext(event.getFacesContext()),
(context, target) -> {
if (target.getId() != null
&& target.getId().startsWith("new-feature-")
&& !show) {
target.setRendered(false);
}
return VisitResult.ACCEPT;
});
}
}

View File

@ -0,0 +1,48 @@
package com.stackify.deepjsf;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.event.ValueChangeEvent;
@ManagedBean
@SessionScoped
public class UserBean {
private String name = "";
private String lastName = "";
private String proposedLogin = "";
public void nameChanged(ValueChangeEvent event) {
this.proposedLogin = event.getNewValue() + "-" + lastName;
}
public void lastNameChanged(ValueChangeEvent event) {
this.proposedLogin = name + "-" + event.getNewValue();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getProposedLogin() {
return proposedLogin;
}
public void setProposedLogin(String proposedLogin) {
this.proposedLogin = proposedLogin;
}
}

View File

@ -0,0 +1,14 @@
package com.stackify.deepjsf;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
@ManagedBean
@RequestScoped
public class UserControllerBean {
public String register() {
return "register-success";
}
}

View File

@ -0,0 +1,15 @@
<?xml version='1.0' encoding='UTF-8'?>
<faces-config version="2.2" 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-facesconfig_2_2.xsd">
<navigation-rule>
<from-view-id>/register.xhtml</from-view-id>
<navigation-case>
<from-outcome>register-success</from-outcome>
<to-view-id>/hello.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
</faces-config>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<f:view beforePhase="#{phaseListenerBean.beforeListener}">
<h:outputLabel value="Hello, #{userBean.name}"/>
<h:outputLabel id="new-feature-last-name" value=" #{userBean.lastName}"/>
</f:view>
</html>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<f:view>
<h:outputLabel value="Hello, #{userBean.name} #{userBean.lastName}! Your login is: #{userBean.proposedLogin}"/>
</f:view>
</html>

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<f:view beforePhase="#{phaseListenerBean.beforeListener}">
<h:form>
<h:panelGrid columns="2">
<h:outputLabel value="First Name:"/>
<h:inputText id="name" value="#{userBean.name}"/>
<h:outputLabel id="new-feature-last-name-label" value="Last Name:"/>
<h:inputText id="new-feature-last-name" value="#{userBean.lastName}"/>
<h:commandButton value="Submit" action="#{greetControllerBean.greet}"/>
</h:panelGrid>
</h:form>
</f:view>
</html>

View File

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
<h:outputScript library="javax.faces" name="jsf.js"/>
</h:head>
<f:view>
<h:form>
<h:panelGrid columns="2">
<h:outputLabel value="First Name:"/>
<h:inputText id="name" value="#{userBean.name}"
valueChangeListener="#{userBean.nameChanged}">
<f:ajax event="change" execute="@this" render="proposed-login"/>
</h:inputText>
<h:outputLabel id="lastname-label" value="Last Name:"/>
<h:inputText id="lastname" value="#{userBean.lastName}"
valueChangeListener="#{userBean.lastNameChanged}">
<f:ajax event="change" execute="@this" render="proposed-login"/>
</h:inputText>
<h:outputLabel id="login-label" value="Proposed Login:"/>
<h:inputText id="proposed-login" disabled="true" value="#{userBean.proposedLogin}"/>
<h:commandButton value="Submit" action="#{userControllerBean.register}"/>
</h:panelGrid>
</h:form>
</f:view>
</html>

View File

@ -5,3 +5,5 @@
- [Hibernate Mapping Date and Time](http://www.baeldung.com/hibernate-date-time)
- [Hibernate Inheritance Mapping](http://www.baeldung.com/hibernate-inheritance)
- [A Guide to Multitenancy in Hibernate 5](http://www.baeldung.com/hibernate-5-multitenancy)
- [Introduction to Hibernate Spatial](http://www.baeldung.com/hibernate-spatial)
- [Hibernate Interceptors](http://www.baeldung.com/hibernate-interceptor)

View File

@ -2,6 +2,7 @@
### Relevant Article:
- [Introduction to using InfluxDB with Java](http://www.baeldung.com/using-influxdb-with-java/)
- [Using InfluxDB with Java](http://www.baeldung.com/java-influxdb)
### Overview
This Maven project contains the Java code for the article linked above.

View File

@ -38,4 +38,9 @@ $ curl -X POST -H "Content-Type:application/json" -d '{ "firstName" : "Dassi", "
Now with default configurations it will be available at: [http://localhost:8080](http://localhost:8080)
Enjoy it :)
Enjoy it :)
### Relevant Articles:
- [Intro to Performance Testing using JMeter](http://www.baeldung.com/jmeter)
- [Configure Jenkins to Run and Show JMeter Tests](http://www.baeldung.com/jenkins-and-jmeter)

View File

@ -2,3 +2,4 @@
- [Introduction to Reladomo](http://www.baeldung.com/reladomo)
- [Introduction to ORMLite](http://www.baeldung.com/ormlite)
- [Introduction To Kryo](http://www.baeldung.com/kryo)
- [Introduction to KafkaStreams in Java](http://www.baeldung.com/java-kafka-streams)

View File

@ -58,6 +58,8 @@
- [Introduction to BouncyCastle with Java](http://www.baeldung.com/java-bouncy-castle)
- [Intro to JDO Queries 2/2](http://www.baeldung.com/jdo-queries)
- [Guide to google-http-client](http://www.baeldung.com/google-http-client)
- [Interact with Google Sheets from Java](http://www.baeldung.com/google-sheets-java-client)
The libraries module contains examples related to small libraries that are relatively easy to use and does not require any separate module of its own.

View File

@ -1,3 +1,6 @@
## Logging Modules
### Relevant Articles:
- [Creating a Custom Logback Appender](http://www.baeldung.com/custom-logback-appender)

4
lucene/README.md Normal file
View File

@ -0,0 +1,4 @@
### Relevant Articles:
- [Introduction to Apache Lucene](http://www.baeldung.com/lucene)
- [A Simple File Search with Lucene](http://www.baeldung.com/lucene-file-search)

3
muleesb/README.md Normal file
View File

@ -0,0 +1,3 @@
### Relevant Articles:
- [Getting Started With Mule ESB](http://www.baeldung.com/mule-esb)

View File

@ -22,4 +22,7 @@ $ mvn clean install
Before launching unit tests:
- Install OrientDB
- Create BaeldungDB, BaeldungDBTwo and BaeldungDBThree databases
- Uncomment annotations on the test files
- Uncomment annotations on the test files
### Relevant Articles:
- [Introduction to the OrientDB Java APIs](http://www.baeldung.com/java-orientdb)

View File

@ -1,3 +1,7 @@
## Persistence Modules
### Relevant Articles:
- [Introduction to Hibernate Search](http://www.baeldung.com/hibernate-search)

View File

@ -30,6 +30,10 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
</dependency>
<!-- oauth2 -->
<dependency>
@ -40,6 +44,21 @@
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-jose</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>

View File

@ -0,0 +1,54 @@
package com.baeldung.securityextrafields;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
public class CustomAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
public static final String SPRING_SECURITY_FORM_DOMAIN_KEY = "domain";
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException {
if (!request.getMethod()
.equals("POST")) {
throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
}
UsernamePasswordAuthenticationToken authRequest = getAuthRequest(request);
setDetails(request, authRequest);
return this.getAuthenticationManager()
.authenticate(authRequest);
}
private UsernamePasswordAuthenticationToken getAuthRequest(HttpServletRequest request) {
String username = obtainUsername(request);
String password = obtainPassword(request);
String domain = obtainDomain(request);
if (username == null) {
username = "";
}
if (password == null) {
password = "";
}
if (domain == null) {
domain = "";
}
String usernameDomain = String.format("%s%s%s", username.trim(),
String.valueOf(Character.LINE_SEPARATOR), domain);
return new UsernamePasswordAuthenticationToken(usernameDomain, password);
}
private String obtainDomain(HttpServletRequest request) {
return request.getParameter(SPRING_SECURITY_FORM_DOMAIN_KEY);
}
}

View File

@ -0,0 +1,32 @@
package com.baeldung.securityextrafields;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
@Service("userDetailsService")
public class CustomUserDetailsService implements UserDetailsService {
private final UserRepository userRepository;
public CustomUserDetailsService(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
String[] usernameAndDomain = StringUtils.split(username, String.valueOf(Character.LINE_SEPARATOR));
if (usernameAndDomain == null || usernameAndDomain.length != 2) {
throw new UsernameNotFoundException("Username and domain must be provided");
}
User user = userRepository.findUser(usernameAndDomain[0], usernameAndDomain[1]);
if (user == null) {
throw new UsernameNotFoundException(
String.format("Username not found for domain, username=%s, domain=%s",
usernameAndDomain[0], usernameAndDomain[1]));
}
return user;
}
}

View File

@ -0,0 +1,26 @@
package com.baeldung.securityextrafields;
import java.util.ArrayList;
import java.util.Collection;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Repository;
@Repository("userRepository")
public class CustomUserRepository implements UserRepository {
@Override
public User findUser(String username, String domain) {
if (StringUtils.isAnyBlank(username, domain)) {
return null;
} else {
Collection<? extends GrantedAuthority> authorities = new ArrayList<>();
User user = new User(username, domain,
"$2a$10$U3GhSMpsMSOE8Kqsbn58/edxDBKlVuYMh7qk/7ErApYFjJzi2VG5K", true,
true, true, true, authorities);
return user;
}
}
}

View File

@ -0,0 +1,65 @@
package com.baeldung.securityextrafields;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.PropertySource;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@EnableWebSecurity
@PropertySource("classpath:/application-extrafields.properties")
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.addFilterBefore(authenticationFilter(), UsernamePasswordAuthenticationFilter.class)
.authorizeRequests()
.antMatchers("/css/**", "/index").permitAll()
.antMatchers("/user/**").authenticated()
.and()
.formLogin().loginPage("/login")
.and()
.logout()
.logoutUrl("/logout");
}
public CustomAuthenticationFilter authenticationFilter() throws Exception {
CustomAuthenticationFilter filter = new CustomAuthenticationFilter();
filter.setAuthenticationManager(authenticationManagerBean());
filter.setAuthenticationFailureHandler(failureHandler());
return filter;
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authProvider());
}
public AuthenticationProvider authProvider() {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setUserDetailsService(userDetailsService);
provider.setPasswordEncoder(passwordEncoder());
return provider;
}
public SimpleUrlAuthenticationFailureHandler failureHandler() {
return new SimpleUrlAuthenticationFailureHandler("/login?error=true");
}
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}

View File

@ -0,0 +1,13 @@
package com.baeldung.securityextrafields;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringExtraLoginFieldsApplication {
public static void main(String[] args) {
SpringApplication.run(SpringExtraLoginFieldsApplication.class, args);
}
}

View File

@ -0,0 +1,23 @@
package com.baeldung.securityextrafields;
import java.util.Collection;
import org.springframework.security.core.GrantedAuthority;
public class User extends org.springframework.security.core.userdetails.User {
private static final long serialVersionUID = 1L;
private final String domain;
public User(String username, String domain, String password, boolean enabled,
boolean accountNonExpired, boolean credentialsNonExpired,
boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) {
super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
this.domain = domain;
}
public String getDomain() {
return domain;
}
}

View File

@ -0,0 +1,7 @@
package com.baeldung.securityextrafields;
public interface UserRepository {
public User findUser(String username, String domain);
}

View File

@ -0,0 +1,51 @@
package com.baeldung.securityextrafields;
import java.util.Optional;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class WebController {
@RequestMapping("/")
public String root() {
return "redirect:/index";
}
@RequestMapping("/index")
public String index(Model model) {
getDomain().ifPresent(d -> {
model.addAttribute("domain", d);
});
return "index";
}
@RequestMapping("/user/index")
public String userIndex(Model model) {
getDomain().ifPresent(d -> {
model.addAttribute("domain", d);
});
return "user/index";
}
@RequestMapping("/login")
public String login() {
return "login";
}
private Optional<String> getDomain() {
Authentication auth = SecurityContextHolder.getContext()
.getAuthentication();
String domain = null;
if (auth != null && !auth.getClass().equals(AnonymousAuthenticationToken.class)) {
User user = (User) auth.getPrincipal();
domain = user.getDomain();
}
return Optional.ofNullable(domain);
}
}

View File

@ -0,0 +1 @@
spring.thymeleaf.prefix = classpath:/templatesextrafields/

View File

@ -0,0 +1,18 @@
body {
font-family: sans;
font-size: 1em;
}
p.error {
font-weight: bold;
color: red;
}
div.logout {
float: right;
}
.formfield {
margin: 0.5em;
padding: 0.3em;
}

View File

@ -0,0 +1,24 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
<head>
<title>Spring Security - Login With Extra Fields</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="/css/main.css" th:href="@{/css/main.css}" />
</head>
<body>
<div th:fragment="logout" class="logout" sec:authorize="isAuthenticated()">
Logged in user: <span sec:authentication="name"></span> |
domain: <span th:text="${domain}">Some Domain</span>
<div>
<form action="#" th:action="@{/logout}" method="post">
<input type="submit" value="Logout" />
</form>
</div>
</div>
<h1>Hello Spring Security</h1>
<p>This is an unsecured page, but you can access the secured pages after authenticating.</p>
<ul>
<li>Go to the <a href="/user/index" th:href="@{/user/index}">secured pages</a></li>
</ul>
</body>
</html>

View File

@ -0,0 +1,23 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<title>Login page</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="/css/main.css" th:href="@{/css/main.css}" />
</head>
<body>
<h1>Login page</h1>
<p>Example: user / domain / password</p>
<p th:if="${param.error}" class="error">Invalid user, password, or domain</p>
<form th:action="@{/login}" method="post">
<label for="username">Username</label>:
<input class="formfield" type="text" id="username" name="username" autofocus="autofocus" /> <br />
<label for="domain">Domain</label>:
<input class="formfield" type="text" id="domain" name="domain" /> <br />
<label for="password">Password</label>:
<input class="formfield" type="password" id="password" name="password" /> <br />
<input type="submit" value="Log in" />
</form>
<p><a href="/index" th:href="@{/index}">Back to home page</a></p>
</body>
</html>

View File

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<title>Spring Security - Login With Extra Fields</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="/css/main.css" th:href="@{/css/main.css}" />
</head>
<body>
<div th:replace="index::logout"></div>
<h1>This is a secured page!</h1>
<p><a href="/index" th:href="@{/index}">Back to home page</a></p>
</body>
</html>

View File

@ -0,0 +1,103 @@
package com.baeldung.securityextrafields;
import static org.junit.Assert.assertEquals;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrlPattern;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import java.util.ArrayList;
import java.util.Collection;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.mock.web.MockHttpSession;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.web.FilterChainProxy;
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
import org.springframework.test.context.junit.jupiter.web.SpringJUnitWebConfig;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
@RunWith(SpringRunner.class)
@SpringJUnitWebConfig
@SpringBootTest(classes = SpringExtraLoginFieldsApplication.class)
public class SecurityExtraFieldsTest {
@Autowired
private FilterChainProxy springSecurityFilterChain;
@Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
@Before
public void setup() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(wac)
.apply(springSecurity(springSecurityFilterChain)).build();
}
@Test
public void givenRootPathAccess_thenRedirectToIndex() throws Exception {
this.mockMvc.perform(get("/"))
.andExpect(status().is3xxRedirection())
.andExpect(redirectedUrlPattern("/index*"));
}
@Test
public void givenSecuredResource_whenAccessUnauthenticated_thenRequiresAuthentication() throws Exception {
this.mockMvc.perform(get("/user/index"))
.andExpect(status().is3xxRedirection())
.andExpect(redirectedUrlPattern("**/login"));
}
@Test
public void givenAccessSecuredResource_whenAuthenticated_thenAuthHasExtraFields() throws Exception {
MockHttpServletRequestBuilder securedResourceAccess = get("/user/index");
MvcResult unauthenticatedResult = mockMvc.perform(securedResourceAccess)
.andExpect(status().is3xxRedirection())
.andReturn();
MockHttpSession session = (MockHttpSession) unauthenticatedResult.getRequest()
.getSession();
String loginUrl = unauthenticatedResult.getResponse()
.getRedirectedUrl();
User user = getUser();
mockMvc.perform(post(loginUrl)
.param("username", user.getUsername())
.param("password", user.getPassword())
.param("domain", user.getDomain())
.session(session)
.with(csrf()))
.andExpect(status().is3xxRedirection())
.andExpect(redirectedUrlPattern("**/user/index"))
.andReturn();
mockMvc.perform(securedResourceAccess.session(session))
.andExpect(status().isOk());
SecurityContext securityContext
= (SecurityContext) session.getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY);
Authentication auth = securityContext.getAuthentication();
assertEquals(((User)auth.getPrincipal()).getDomain(), user.getDomain());
}
private User getUser() {
Collection<? extends GrantedAuthority> authorities = new ArrayList<>();
return new User("myusername", "mydomain", "password", true, true, true, true, authorities);
}
}

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

@ -19,4 +19,6 @@
### Relevant Articles:
- [Introduction to Spring Cloud Rest Client with Netflix Ribbon](http://www.baeldung.com/spring-cloud-rest-client-with-netflix-ribbon)
[An Introduction to Spring Cloud Zookeeper](http://www.baeldung.com/spring-cloud-zookeeper)
- [An Introduction to Spring Cloud Zookeeper](http://www.baeldung.com/spring-cloud-zookeeper)
- [Spring Cloud Connectors and Heroku](http://www.baeldung.com/spring-cloud-heroku)

View File

@ -0,0 +1,29 @@
# README #
This README would normally document whatever steps are necessary to get your application up and running.
### What is this repository for? ###
* Quick summary
* Version
* [Learn Markdown](https://bitbucket.org/tutorials/markdowndemo)
### How do I get set up? ###
* Summary of set up
* Configuration
* Dependencies
* Database configuration
* How to run tests
* Deployment instructions
### Contribution guidelines ###
* Writing tests
* Code review
* Other guidelines
### Who do I talk to? ###
* Repo owner or admin
* Other community or team contact

View File

@ -0,0 +1,28 @@
myauthkey
security:
oauth2:
resource:
jwt:
keyValue: |
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjj4JDMgT4OoaXisEd8Nz
uiLwum9mh8BH1l9Atpe+uZkepf3Vnv0Bhxn0BGR+kYGwEHZPVpWsHEyTfIRdinaQ
vlPaxWJquQW25yYstrCuQTKJvFjSO/cX/V4OGi1RUj76mOpwzkm1Kui3R7Sfh8Zo
WO0GiWIFJqNBsZ9b1wOfBMXnge+A+u/qxVNnTFpwCVj6k2Yb4YUsmLNCmND7E3Ra
BnrNQWqMU2numhV+ADpmVH08m/+pWdZ896uYu/tvQnz3agvZPcFsEst7LcNAWQFT
eNLkfwVfepKWa9jPELemtTLf1MkMppU+Lj1UNCr8x4Y6EupRDZhplVNtqYsPNDpO
7wIDAQAB
-----END PUBLIC KEY-----
jwt:
certificate:
store:
file: classpath:/certificate/my-auth-server.jks
password: storepassword
key:
alias: myauthserver
password: keypassword

View File

@ -0,0 +1,42 @@
<?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>
<groupId>com.baeldung</groupId>
<artifactId>authserver</artifactId>
<version>0.0.1-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
<version>1.1.2.RELEASE</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,12 @@
package com.baeldung;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.*;
@SpringBootApplication
public class AuthServer {
public static void main(String[] args) {
SpringApplication.run(AuthServer.class, args);
}
}

View File

@ -0,0 +1,77 @@
package com.baeldung.config;
import java.security.KeyPair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.Resource;
import org.springframework.security.core.userdetails.UserDetailsService;
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.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.KeyStoreKeyFactory;
@Configuration
@EnableAuthorizationServer
@Order(6)
public class AuthServerConfigurer
extends
AuthorizationServerConfigurerAdapter {
@Value("${jwt.certificate.store.file}")
private Resource keystore;
@Value("${jwt.certificate.store.password}")
private String keystorePassword;
@Value("${jwt.certificate.key.alias}")
private String keyAlias;
@Value("${jwt.certificate.key.password}")
private String keyPassword;
@Autowired
private UserDetailsService userDetailsService;
@Override
public void configure(
ClientDetailsServiceConfigurer clients)
throws Exception {
clients
.inMemory()
.withClient("authserver")
.secret("passwordforauthserver")
.redirectUris("http://localhost:8080/")
.authorizedGrantTypes("authorization_code",
"refresh_token")
.scopes("myscope")
.autoApprove(true)
.accessTokenValiditySeconds(30)
.refreshTokenValiditySeconds(1800);
}
@Override
public void configure(
AuthorizationServerEndpointsConfigurer endpoints)
throws Exception {
endpoints
.accessTokenConverter(jwtAccessTokenConverter())
.userDetailsService(userDetailsService);
}
@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter() {
KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(
keystore, keystorePassword.toCharArray());
KeyPair keyPair = keyStoreKeyFactory.getKeyPair(
keyAlias, keyPassword.toCharArray());
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setKeyPair(keyPair);
return converter;
}
}

View File

@ -0,0 +1,21 @@
package com.baeldung.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
/**
* Our configuration for the OAuth2 User Info Resource Server.
*/
@Configuration
@EnableResourceServer
public class ResourceServerConfigurer extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.antMatcher("/user")
.authorizeRequests()
.anyRequest()
.authenticated();
}
}

View File

@ -0,0 +1,14 @@
package com.baeldung.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@Configuration
public class WebMvcConfigurer extends WebMvcConfigurerAdapter {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("login").setViewName("login");
}
}

View File

@ -0,0 +1,52 @@
package com.baeldung.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableOAuth2Client;
@Configuration
@EnableWebSecurity
@EnableOAuth2Client
public class WebSecurityConfigurer
extends
WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http)
throws Exception {
http
.authorizeRequests()
.antMatchers("/login**").permitAll()
.anyRequest().authenticated()
.and().csrf()
.and().formLogin().loginPage("/login");
}
@Override
protected void configure(
AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("user")
.roles("USER")
.and()
.withUser("admin").password("admin")
.roles("USER", "ADMIN");
}
@Override
@Bean(name = "userDetailsService")
public UserDetailsService userDetailsServiceBean()
throws Exception {
return super.userDetailsServiceBean();
}
}

View File

@ -0,0 +1,20 @@
package com.baeldung.controller;
import java.security.Principal;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* Because this application is also a User Info Resource Server, we expose info about the logged in user at:
*
* http://localhost:9090/auth/user
*/
@RestController
public class ResourceController {
@RequestMapping("/user")
public Principal user(Principal user) {
return user;
}
}

View File

@ -0,0 +1,21 @@
# Make the application available at http://localhost:7070/authserver
server:
port: 7070
contextPath: /authserver
# Our certificate settings for enabling JWT tokens
jwt:
certificate:
store:
file: classpath:/certificate/mykeystore.jks
password: abirkhan04
key:
alias: myauthkey
password: abirkhan04
security:
oauth2:
resource:
filter-order: 3

View File

@ -0,0 +1,29 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8"/>
<title>Baeldung Spring cloud Security</title>
</head>
<body onload="document.f.username.focus();">
<h1>Login</h1>
<form th:action="@{/login}" name="f" method="post">
<fieldset>
<h2> Username and Password:</h2>
<p>
<label for="username">Username</label>
<input type="text" id="username" name="username"/>
</p>
<p>
<label for="password">Password</label>
<input type="password" id="password" name="password"/>
</p>
<p>
<input name="submit" type="submit" value="Login"/>
</p>
</fieldset>
</form>
</body>
</html>

Binary file not shown.

View File

@ -0,0 +1,102 @@
<?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>
<groupId>com.baeldung</groupId>
<artifactId>oauth2client</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>oauth2client</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.SR4</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<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-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>webjars-locator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>js-cookie</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,22 @@
package com.baeldung;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import com.baeldung.filters.SimpleFilter;
@SpringBootApplication
public class CloudSite {
public static void main(String[] args) {
SpringApplication.run(CloudSite.class, args);
}
@Bean
public SimpleFilter simpleFilter() {
return new SimpleFilter();
}
}

View File

@ -0,0 +1,49 @@
package com.baeldung.config;
import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.oauth2.client.OAuth2ClientContext;
import org.springframework.security.oauth2.client.OAuth2RestOperations;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
@EnableZuulProxy
@Configuration
@EnableOAuth2Sso
public class SiteSecurityConfigurer
extends
WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http)
throws Exception {
http.antMatcher("/**")
.authorizeRequests()
.antMatchers("/", "/webjars/**")
.permitAll()
.anyRequest()
.authenticated()
.and()
.logout()
.logoutSuccessUrl("/")
.permitAll()
.and()
.csrf()
.csrfTokenRepository(
CookieCsrfTokenRepository
.withHttpOnlyFalse());
}
@Bean
public OAuth2RestOperations restOperations(
OAuth2ProtectedResourceDetails resource,
OAuth2ClientContext context) {
return new OAuth2RestTemplate(resource, context);
}
}

View File

@ -0,0 +1,30 @@
package com.baeldung.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestOperations;
import org.springframework.web.servlet.ModelAndView;
@RestController
public class CloudSiteController {
@Autowired
private RestOperations restOperations;
@GetMapping("/")
@ResponseBody
public String helloFromBaeldung() {
return "Hello From Baeldung!";
}
@GetMapping("/person")
public ModelAndView person() {
ModelAndView mav = new ModelAndView("personinfo");
String personResourceUrl = "http://localhost:9000/personResource";
mav.addObject("person", restOperations.getForObject(personResourceUrl, String.class));
return mav;
}
}

View File

@ -0,0 +1,39 @@
package com.baeldung.filters;
import javax.servlet.http.HttpServletRequest;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.ZuulFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SimpleFilter extends ZuulFilter {
private static Logger log = LoggerFactory.getLogger(SimpleFilter.class);
@Override
public String filterType() {
return "pre";
}
@Override
public int filterOrder() {
return 1;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
log.info(String.format("%s request to %s", request.getMethod(), request.getRequestURL().toString()));
return null;
}
}

View File

@ -0,0 +1,37 @@
# Make the application available at http://localhost:8080
# These are default settings, but we add them for clarity.
server:
port: 8080
contextPath: /
# Configure the Authorization Server and User Info Resource Server details
security:
oauth2:
client:
accessTokenUri: http://localhost:7070/authserver/oauth/token
userAuthorizationUri: http://localhost:7070/authserver/oauth/authorize
clientId: authserver
clientSecret: passwordforauthserver
resource:
userInfoUri: http://localhost:7070/authserver/user
person:
url: http://localhost:9000/person
# Proxies the calls to http://localhost:8080/api/* to our REST service at http://localhost:8081/*
# and automatically includes our OAuth2 token in the request headers
zuul:
routes:
resource:
path: /api/**
url: http://localhost:9000
user:
path: /user/**
url: http://localhost:7070/authserver/user
# Make sure the OAuth2 token is only relayed when using the internal API,
# do not pass any authentication to the external API
proxy:
auth:
routes:
api: oauth2

View File

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8" />
<title>Getting Personal Information</title>
</head>
<body>
<h1>Providing Person Information</h1>
<p>
Person's information: <span id="personInfo" th:text="${person}"></span>
</p>
</body>
</html>

View File

@ -0,0 +1,16 @@
package com.example.springoath2;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class Springoath2ApplicationTests {
@Test
public void contextLoads() {
}
}

View File

@ -0,0 +1,74 @@
<?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>
<groupId>com.baeldung</groupId>
<artifactId>personresource</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>personresource</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Edgware.RELEASE</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-jwt</artifactId>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,12 @@
package com.baeldung;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

View File

@ -0,0 +1,25 @@
package com.baeldung.config;
import org.springframework.context.annotation.Configuration;
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.configuration.EnableWebSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
/**
* REST API Resource Server.
*/
@Configuration
@EnableWebSecurity
@EnableResourceServer
@EnableGlobalMethodSecurity(prePostEnabled = true) // Allow method annotations like @PreAuthorize
public class ResourceConfigurer extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.httpBasic().disable();
http.authorizeRequests().anyRequest().authenticated();
}
}

View File

@ -0,0 +1,21 @@
package com.baeldung.controller;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import com.baeldung.model.Person;
import com.google.gson.Gson;
@RestController
public class PersonInfoController {
@GetMapping("/personResource")
@PreAuthorize("hasAnyRole('ADMIN', 'USER')")
public @ResponseBody String personInfo() {
Gson gson = new Gson();
String person = gson.toJson(new Person("abir", "Dhaka", "Bangladesh", 29, "Male"));
return person;
}
}

View File

@ -0,0 +1,59 @@
package com.baeldung.model;
public class Person {
private String name;
private String city;
private String country;
private Integer age;
private String sex;
public Person(String name, String city, String country, Integer age, String sex) {
this.name = name;
this.city = city;
this.country = country;
this.age = age;
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}

View File

@ -0,0 +1,22 @@
# Make the application available at http://localhost:9000
server:
port: 9000
# Configure the public key to use for verifying the incoming JWT tokens
security:
sessions: NEVER
oauth2:
resource:
userInfoUri: http://localhost:7070/authserver/user
jwt:
keyValue: |
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhiiifKv6Otf5PyqIE+LQ
EiJRRh6q8piPY9Okq+RfRu9Bue0D8hq7aFxcgkLZ6Bg9CAS+w1KdaE5MMeOCVVxv
rpRETzVpAsh6GL5nBc679jSqMzjr3V4uty46ilL4VHKSxlZh5Nmz5EMHPI5iwpNs
8U5n3QiwsTk514FXad54xPSPH3i/pDzGSZHrVcwDVaOKn7gFiIqP86vkJB47JZv8
T6P5RK7Rj06zoG45DMGWG3DQv6o1/Jm4IJQWj0AUD3bSHqzXkPr7qyMYvkE4kyMH
6aVAsAYMxilZFlJMv2b8N883gdi3LEeOJo8zZr5IWyyROfepdeOL7UkAXddAj+dL
WQIDAQAB
-----END PUBLIC KEY-----

View File

@ -0,0 +1,16 @@
package com.baeldung.service.personservice;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonserviceApplicationTests {
@Test
public void contextLoads() {
}
}

View File

@ -0,0 +1,30 @@
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhiiifKv6Otf5PyqIE+LQ
EiJRRh6q8piPY9Okq+RfRu9Bue0D8hq7aFxcgkLZ6Bg9CAS+w1KdaE5MMeOCVVxv
rpRETzVpAsh6GL5nBc679jSqMzjr3V4uty46ilL4VHKSxlZh5Nmz5EMHPI5iwpNs
8U5n3QiwsTk514FXad54xPSPH3i/pDzGSZHrVcwDVaOKn7gFiIqP86vkJB47JZv8
T6P5RK7Rj06zoG45DMGWG3DQv6o1/Jm4IJQWj0AUD3bSHqzXkPr7qyMYvkE4kyMH
6aVAsAYMxilZFlJMv2b8N883gdi3LEeOJo8zZr5IWyyROfepdeOL7UkAXddAj+dL
WQIDAQAB
-----END PUBLIC KEY-----
-----BEGIN CERTIFICATE-----
MIIDfzCCAmegAwIBAgIEDqsC7jANBgkqhkiG9w0BAQsFADBwMQswCQYDVQQGEwI4
ODETMBEGA1UECBMKQmFuZ2xhZGVzaDEOMAwGA1UEBxMFRGhha2ExETAPBgNVBAoT
CEJhZWxkdW5nMRUwEwYDVQQLEwxCYWVsZHVuZ2Jsb2cxEjAQBgNVBAMTCWxvY2Fs
aG9zdDAeFw0xNzEyMjUxNDE0MDhaFw0xODAzMjUxNDE0MDhaMHAxCzAJBgNVBAYT
Ajg4MRMwEQYDVQQIEwpCYW5nbGFkZXNoMQ4wDAYDVQQHEwVEaGFrYTERMA8GA1UE
ChMIQmFlbGR1bmcxFTATBgNVBAsTDEJhZWxkdW5nYmxvZzESMBAGA1UEAxMJbG9j
YWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhiiifKv6Otf5
PyqIE+LQEiJRRh6q8piPY9Okq+RfRu9Bue0D8hq7aFxcgkLZ6Bg9CAS+w1KdaE5M
MeOCVVxvrpRETzVpAsh6GL5nBc679jSqMzjr3V4uty46ilL4VHKSxlZh5Nmz5EMH
PI5iwpNs8U5n3QiwsTk514FXad54xPSPH3i/pDzGSZHrVcwDVaOKn7gFiIqP86vk
JB47JZv8T6P5RK7Rj06zoG45DMGWG3DQv6o1/Jm4IJQWj0AUD3bSHqzXkPr7qyMY
vkE4kyMH6aVAsAYMxilZFlJMv2b8N883gdi3LEeOJo8zZr5IWyyROfepdeOL7UkA
XddAj+dLWQIDAQABoyEwHzAdBgNVHQ4EFgQUHLFYkq36Wami5qsVRe/1eQedmdgw
DQYJKoZIhvcNAQELBQADggEBABL3lYyuRd6Hv8DPus/zQL0bRl6gVsEzczwmWMUA
3NJZbUHAD/KC732aArvKIKykkbLG6K/Mhnfuu8YBfWzTvGgY3Ww+ka2sJFOsUW7r
sa6OBtNHh4zhDYN2Weza+4jnRLxtkzFbm6v2sheFkyB1NywCwFE/6p1Z6KTG8RyJ
gw/OHl6rb+Y/T6cOeeTCFUN/v+qRVSB9I/MjSK5wRNbFT+MyNUeL6gsiyIvxSZbj
y4vrjGHkXasSmwkfvgw67mJMk4XTGrVLjIXUTyzbdSmodcv8N6nrsIk4SBYCnTrI
E/5NtNgbOFGwovde5yNrZIjjAC1VGOmVFhcxFJpwT6ZkSks=
-----END CERTIFICATE-----

View File

@ -21,12 +21,17 @@ public class EurekaClientApplication implements GreetingController {
@Value("${spring.application.name}")
private String appName;
@Value("${server.port}")
private String portNumber;
public static void main(String[] args) {
SpringApplication.run(EurekaClientApplication.class, args);
}
@Override
public String greeting() {
return String.format("Hello from '%s'!", eurekaClient.getApplication(appName).getName());
System.out.println("Request received on port number " + portNumber);
return String.format("Hello from '%s with Port Number %s'!", eurekaClient.getApplication(appName)
.getName(), portNumber);
}
}

View File

@ -3,7 +3,7 @@ spring:
name: spring-cloud-eureka-client
server:
port: 0
port: 8081
eureka:
client:

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);
}
}

3
spring-ejb/README.md Normal file
View File

@ -0,0 +1,3 @@
### Relevant Articles
- [Integration Guide for Spring and EJB](http://www.baeldung.com/spring-ejb)

View File

@ -4,11 +4,11 @@
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd">
http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd">
<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager" />
<context:component-scan base-package="com.baeldung.spring.controller" />

View File

@ -3,11 +3,11 @@
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd"
http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd"
>
<mvc:annotation-driven>

View File

@ -2,9 +2,9 @@
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.baeldung.spring.controller"/>
@ -58,4 +58,4 @@
<!-- End: Mapping by ControllerClassNameHandlerMapping with prefix -->
</beans>
</beans>

Some files were not shown because too many files have changed in this diff Show More