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: ### Relevant Articles:
- [Microsoft Word Processing in Java with Apache POI](http://www.baeldung.com/java-microsoft-word-with-apache-poi) - [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) - [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) - [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) - [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) - [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) - [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) - [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 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) - [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) - [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) - [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) - [Delegated Properties in Kotlin](http://www.baeldung.com/kotlin-delegated-properties)
- [Sealed Classes in Kotlin](http://www.baeldung.com/kotlin-sealed-classes) - [Sealed Classes in Kotlin](http://www.baeldung.com/kotlin-sealed-classes)
- [JUnit 5 for Kotlin Developers](http://www.baeldung.com/junit-5-kotlin) - [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: ## 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: ### Relevant Articles:
- [Database Migrations with Flyway](http://www.baeldung.com/database-migrations-with-flyway) - [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: ## Relevant articles:
- [Introduction to Gradle](http://www.baeldung.com/gradle) - [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 Mapping Date and Time](http://www.baeldung.com/hibernate-date-time)
- [Hibernate Inheritance Mapping](http://www.baeldung.com/hibernate-inheritance) - [Hibernate Inheritance Mapping](http://www.baeldung.com/hibernate-inheritance)
- [A Guide to Multitenancy in Hibernate 5](http://www.baeldung.com/hibernate-5-multitenancy) - [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: ### Relevant Article:
- [Introduction to using InfluxDB with Java](http://www.baeldung.com/using-influxdb-with-java/) - [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 ### Overview
This Maven project contains the Java code for the article linked above. 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) 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 Reladomo](http://www.baeldung.com/reladomo)
- [Introduction to ORMLite](http://www.baeldung.com/ormlite) - [Introduction to ORMLite](http://www.baeldung.com/ormlite)
- [Introduction To Kryo](http://www.baeldung.com/kryo) - [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) - [Introduction to BouncyCastle with Java](http://www.baeldung.com/java-bouncy-castle)
- [Intro to JDO Queries 2/2](http://www.baeldung.com/jdo-queries) - [Intro to JDO Queries 2/2](http://www.baeldung.com/jdo-queries)
- [Guide to google-http-client](http://www.baeldung.com/google-http-client) - [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. 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 ## 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: Before launching unit tests:
- Install OrientDB - Install OrientDB
- Create BaeldungDB, BaeldungDBTwo and BaeldungDBThree databases - 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 ## 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> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId> <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
</dependency>
<!-- oauth2 --> <!-- oauth2 -->
<dependency> <dependency>
@ -40,6 +44,21 @@
<groupId>org.springframework.security</groupId> <groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-jose</artifactId> <artifactId>spring-security-oauth2-jose</artifactId>
</dependency> </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> </dependencies>
<build> <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 ### Spring Boot Security Auto-Configuration
- mvn clean install - mvn clean install
- uncomment in application.properties spring.profiles.active=basic # for basic auth config - uncomment actuator dependency simultaneously with the line from basic auth main class
- uncomment in application.properties spring.profiles.active=form # for form based auth config - uncomment security properties for easy testing. If not random will be generated.
- uncomment actuator dependency simultaneously with the line from main class
### 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> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId> <artifactId>spring-boot-starter-security</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId> <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.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
@ -7,7 +7,7 @@ import org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration
@SpringBootApplication(exclude = { @SpringBootApplication(exclude = {
SecurityAutoConfiguration.class SecurityAutoConfiguration.class
// ,ManagementWebSecurityAutoConfiguration.class // ,ManagementWebSecurityAutoConfiguration.class
}) }, scanBasePackages = "com.baeldung.springbootsecurity.basic_auth")
public class SpringBootSecurityApplication { public class SpringBootSecurityApplication {
public static void main(String[] args) { 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.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 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.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
@ -9,8 +8,7 @@ import org.springframework.security.config.annotation.web.configuration.WebSecur
@Configuration @Configuration
@EnableWebSecurity @EnableWebSecurity
@Profile("basic") public class BasicAuthConfiguration extends WebSecurityConfigurerAdapter {
public class BasicConfiguration extends WebSecurityConfigurerAdapter {
@Override @Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception { 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.autoconfigure.exclude=org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration
#spring.profiles.active=form #security.user.password=password
#spring.profiles.active=basic #security.oauth2.client.client-id=client
#security.user.password=password #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.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; 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.boot.test.web.client.TestRestTemplate;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.context.junit4.SpringRunner;
import java.io.IOException; 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; import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
@RunWith(SpringRunner.class) @RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = RANDOM_PORT) @SpringBootTest(webEnvironment = RANDOM_PORT, classes = SpringBootSecurityApplication.class)
@ActiveProfiles("basic") public class BasicAuthConfigurationIntegrationTest {
public class BasicConfigurationIntegrationTest {
TestRestTemplate restTemplate; TestRestTemplate restTemplate;
URL base; 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: ### Relevant Articles:
- [Introduction to Spring Cloud Rest Client with Netflix Ribbon](http://www.baeldung.com/spring-cloud-rest-client-with-netflix-ribbon) - [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}") @Value("${spring.application.name}")
private String appName; private String appName;
@Value("${server.port}")
private String portNumber;
public static void main(String[] args) { public static void main(String[] args) {
SpringApplication.run(EurekaClientApplication.class, args); SpringApplication.run(EurekaClientApplication.class, args);
} }
@Override @Override
public String greeting() { 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 name: spring-cloud-eureka-client
server: server:
port: 0 port: 8081
eureka: eureka:
client: client:

View File

@ -45,6 +45,24 @@
<version>${spring-data-elasticsearch.version}</version> <version>${spring-data-elasticsearch.version}</version>
</dependency> </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> <dependency>
<groupId>org.springframework</groupId> <groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId> <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" xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation=" xsi:schemaLocation="
http://www.springframework.org/schema/beans 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
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
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" /> <mvc:annotation-driven content-negotiation-manager="contentNegotiationManager" />
<context:component-scan base-package="com.baeldung.spring.controller" /> <context:component-scan base-package="com.baeldung.spring.controller" />

View File

@ -3,11 +3,11 @@
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation=" xsi:schemaLocation="
http://www.springframework.org/schema/beans 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
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
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> <mvc:annotation-driven>

View File

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

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