Java-70 Rename modules in Spring Security modules
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
## Spring Security Single Sign On
|
||||
|
||||
This module contains modules about single-sign-on with Spring Security
|
||||
|
||||
### Relevant Articles:
|
||||
|
||||
- [Spring Security Kerberos Integration](https://www.baeldung.com/spring-security-kerberos-integration)
|
||||
- [Simple Single Sign-On with Spring Security OAuth2 (legacy stack)](https://www.baeldung.com/sso-spring-security-oauth2-legacy)
|
||||
33
spring-security-modules/spring-security-oauth2-sso/pom.xml
Normal file
33
spring-security-modules/spring-security-oauth2-sso/pom.xml
Normal file
@@ -0,0 +1,33 @@
|
||||
<?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>spring-security-oauth2-sso</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
<name>spring-security-oauth2-sso</name>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-boot-2</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../../parent-boot-2</relativePath>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
<module>spring-security-sso-auth-server</module>
|
||||
<module>spring-security-sso-ui</module>
|
||||
<module>spring-security-sso-ui-2</module>
|
||||
<module>spring-security-sso-kerberos</module>
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
<rest-assured.version>3.1.0</rest-assured.version>
|
||||
<oauth.version>2.3.3.RELEASE</oauth.version>
|
||||
<oauth-auto.version>2.1.1.RELEASE</oauth-auto.version>
|
||||
<spring-security-kerberos.version>1.0.1.RELEASE</spring-security-kerberos.version>
|
||||
<apacheds-jdbm1.version>2.0.0-M2</apacheds-jdbm1.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>spring-security-sso-auth-server</artifactId>
|
||||
<name>spring-security-sso-auth-server</name>
|
||||
<packaging>war</packaging>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>spring-security-sso</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security.oauth</groupId>
|
||||
<artifactId>spring-security-oauth2</artifactId>
|
||||
<version>${oauth.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.baeldung.config;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
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.AuthorizationServerSecurityConfigurer;
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableAuthorizationServer
|
||||
public class AuthServerConfig extends AuthorizationServerConfigurerAdapter {
|
||||
|
||||
@Autowired
|
||||
private BCryptPasswordEncoder passwordEncoder;
|
||||
|
||||
@Override
|
||||
public void configure(final AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
|
||||
oauthServer.tokenKeyAccess("permitAll()")
|
||||
.checkTokenAccess("isAuthenticated()");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(final ClientDetailsServiceConfigurer clients) throws Exception {
|
||||
clients.inMemory()
|
||||
.withClient("SampleClientId")
|
||||
.secret(passwordEncoder.encode("secret"))
|
||||
.authorizedGrantTypes("authorization_code")
|
||||
.scopes("user_info")
|
||||
.autoApprove(true)
|
||||
.redirectUris("http://localhost:8082/ui/login","http://localhost:8083/ui2/login","http://localhost:8082/login","http://www.example.com/")
|
||||
// .accessTokenValiditySeconds(3600)
|
||||
; // 1 hour
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.baeldung.config;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
|
||||
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableResourceServer
|
||||
public class AuthorizationServerApplication extends SpringBootServletInitializer {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(AuthorizationServerApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.baeldung.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.annotation.Order;
|
||||
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.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
|
||||
@Configuration
|
||||
@Order(1)
|
||||
public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception { // @formatter:off
|
||||
http.requestMatchers()
|
||||
.antMatchers("/login", "/oauth/authorize")
|
||||
.and()
|
||||
.authorizeRequests()
|
||||
.anyRequest()
|
||||
.authenticated()
|
||||
.and()
|
||||
.formLogin()
|
||||
.permitAll()
|
||||
.and().csrf().disable();
|
||||
} // @formatter:on
|
||||
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception { // @formatter:off
|
||||
auth.inMemoryAuthentication()
|
||||
.withUser("john")
|
||||
.password(passwordEncoder().encode("123"))
|
||||
.roles("USER");
|
||||
} // @formatter:on
|
||||
|
||||
@Bean
|
||||
public BCryptPasswordEncoder passwordEncoder(){
|
||||
return new BCryptPasswordEncoder();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.baeldung.config;
|
||||
|
||||
import java.security.Principal;
|
||||
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
public class UserController {
|
||||
|
||||
@RequestMapping("/user/me")
|
||||
public Principal user(Principal principal) {
|
||||
System.out.println(principal);
|
||||
return principal;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
server.port=8081
|
||||
server.servlet.context-path=/auth
|
||||
#logging.level.org.springframework=DEBUG
|
||||
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
|
||||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
</configuration>
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.baeldung;
|
||||
|
||||
import com.baeldung.config.AuthorizationServerApplication;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = AuthorizationServerApplication.class, webEnvironment = WebEnvironment.RANDOM_PORT)
|
||||
public class SpringContextTest {
|
||||
|
||||
@Test
|
||||
public void whenLoadApplication_thenSuccess() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.baeldung;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
import io.restassured.RestAssured;
|
||||
import io.restassured.response.Response;
|
||||
|
||||
public class UserInfoEndpointLiveTest {
|
||||
|
||||
@Test
|
||||
public void givenAccessToken_whenAccessUserInfoEndpoint_thenSuccess() {
|
||||
String accessToken = obtainAccessTokenUsingAuthorizationCodeFlow("john","123");
|
||||
Response response = RestAssured.given().header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken).get("http://localhost:8081/auth/user/me");
|
||||
|
||||
assertEquals(HttpStatus.OK.value(), response.getStatusCode());
|
||||
assertEquals("john", response.jsonPath().get("name"));
|
||||
}
|
||||
|
||||
private String obtainAccessTokenUsingAuthorizationCodeFlow(String username, String password) {
|
||||
final String authServerUri = "http://localhost:8081/auth";
|
||||
final String redirectUrl = "http://www.example.com/";
|
||||
final String authorizeUrl = authServerUri + "/oauth/authorize?response_type=code&client_id=SampleClientId&redirect_uri=" + redirectUrl;
|
||||
final String tokenUrl = authServerUri + "/oauth/token";
|
||||
|
||||
// user login
|
||||
Response response = RestAssured.given().formParams("username", username, "password", password).post(authServerUri + "/login");
|
||||
final String cookieValue = response.getCookie("JSESSIONID");
|
||||
|
||||
// get authorization code
|
||||
RestAssured.given().cookie("JSESSIONID", cookieValue).get(authorizeUrl);
|
||||
response = RestAssured.given().cookie("JSESSIONID", cookieValue).post(authorizeUrl);
|
||||
assertEquals(HttpStatus.FOUND.value(), response.getStatusCode());
|
||||
final String location = response.getHeader(HttpHeaders.LOCATION);
|
||||
final String code = location.substring(location.indexOf("code=") + 5);
|
||||
|
||||
// get access token
|
||||
Map<String, String> params = new HashMap<String, String>();
|
||||
params.put("grant_type", "authorization_code");
|
||||
params.put("code", code);
|
||||
params.put("client_id", "SampleClientId");
|
||||
params.put("redirect_uri", redirectUrl);
|
||||
response = RestAssured.given().auth().basic("SampleClientId", "secret").formParams(params).post(tokenUrl);
|
||||
return response.jsonPath().getString("access_token");
|
||||
}
|
||||
}
|
||||
2
spring-security-modules/spring-security-oauth2-sso/spring-security-sso-kerberos/.gitignore
vendored
Normal file
2
spring-security-modules/spring-security-oauth2-sso/spring-security-sso-kerberos/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
krb-test-workdir/
|
||||
/bin/
|
||||
@@ -0,0 +1,4 @@
|
||||
## Relevant articles:
|
||||
|
||||
- [Spring Security Kerberos Integration With MiniKdc](https://www.baeldung.com/spring-security-kerberos-integration)
|
||||
- [Introduction to SPNEGO/Kerberos Authentication in Spring](https://www.baeldung.com/spring-security-kerberos)
|
||||
@@ -0,0 +1,95 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>spring-security-sso-kerberos</artifactId>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>spring-security-sso</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security.kerberos</groupId>
|
||||
<artifactId>spring-security-kerberos-web</artifactId>
|
||||
<version>${spring-security-kerberos.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security.kerberos</groupId>
|
||||
<artifactId>spring-security-kerberos-client</artifactId>
|
||||
<version>${spring-security-kerberos.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.directory.jdbm</groupId>
|
||||
<artifactId>apacheds-jdbm1</artifactId>
|
||||
<version>${apacheds-jdbm1.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security.kerberos</groupId>
|
||||
<artifactId>spring-security-kerberos-test</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.apache.directory.jdbm</groupId>
|
||||
<artifactId>apacheds-jdbm1</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-log4j12</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
<version>${spring-security-kerberos.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>${basedir}/src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
<includes>
|
||||
<include>**/*</include>
|
||||
</includes>
|
||||
</resource>
|
||||
</resources>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<version>2.7</version>
|
||||
<configuration>
|
||||
<delimiters>
|
||||
<delimiter>@</delimiter>
|
||||
</delimiters>
|
||||
<useDefaultDelimiters>false</useDefaultDelimiters>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.baeldung.intro;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package com.baeldung.intro.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
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.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.kerberos.authentication.KerberosAuthenticationProvider;
|
||||
import org.springframework.security.kerberos.authentication.KerberosServiceAuthenticationProvider;
|
||||
import org.springframework.security.kerberos.authentication.sun.SunJaasKerberosClient;
|
||||
import org.springframework.security.kerberos.authentication.sun.SunJaasKerberosTicketValidator;
|
||||
import org.springframework.security.kerberos.web.authentication.SpnegoAuthenticationProcessingFilter;
|
||||
import org.springframework.security.kerberos.web.authentication.SpnegoEntryPoint;
|
||||
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
|
||||
|
||||
import com.baeldung.intro.security.DummyUserDetailsService;
|
||||
|
||||
@Configuration
|
||||
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http.authorizeRequests()
|
||||
.anyRequest()
|
||||
.authenticated()
|
||||
.and()
|
||||
.addFilterBefore(spnegoAuthenticationProcessingFilter(authenticationManagerBean()), BasicAuthenticationFilter.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Bean
|
||||
public AuthenticationManager authenticationManagerBean() throws Exception {
|
||||
return super.authenticationManagerBean();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth.authenticationProvider(kerberosAuthenticationProvider())
|
||||
.authenticationProvider(kerberosServiceAuthenticationProvider());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public KerberosAuthenticationProvider kerberosAuthenticationProvider() {
|
||||
KerberosAuthenticationProvider provider = new KerberosAuthenticationProvider();
|
||||
SunJaasKerberosClient client = new SunJaasKerberosClient();
|
||||
client.setDebug(true);
|
||||
provider.setKerberosClient(client);
|
||||
provider.setUserDetailsService(dummyUserDetailsService());
|
||||
return provider;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SpnegoEntryPoint spnegoEntryPoint() {
|
||||
return new SpnegoEntryPoint("/login");
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SpnegoAuthenticationProcessingFilter spnegoAuthenticationProcessingFilter(AuthenticationManager authenticationManager) {
|
||||
SpnegoAuthenticationProcessingFilter filter = new SpnegoAuthenticationProcessingFilter();
|
||||
filter.setAuthenticationManager(authenticationManager);
|
||||
return filter;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public KerberosServiceAuthenticationProvider kerberosServiceAuthenticationProvider() {
|
||||
KerberosServiceAuthenticationProvider provider = new KerberosServiceAuthenticationProvider();
|
||||
provider.setTicketValidator(sunJaasKerberosTicketValidator());
|
||||
provider.setUserDetailsService(dummyUserDetailsService());
|
||||
return provider;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SunJaasKerberosTicketValidator sunJaasKerberosTicketValidator() {
|
||||
SunJaasKerberosTicketValidator ticketValidator = new SunJaasKerberosTicketValidator();
|
||||
ticketValidator.setServicePrincipal("HTTP/demo.kerberos.bealdung.com@baeldung.com");
|
||||
ticketValidator.setKeyTabLocation(new FileSystemResource("baeldung.keytab"));
|
||||
ticketValidator.setDebug(true);
|
||||
return ticketValidator;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DummyUserDetailsService dummyUserDetailsService() {
|
||||
return new DummyUserDetailsService();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.baeldung.intro.security;
|
||||
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
|
||||
public class DummyUserDetailsService implements UserDetailsService {
|
||||
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
||||
return new User(username, "notUsed", true, true, true, true, AuthorityUtils.createAuthorityList("ROLE_USER"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package kerberos.client;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
import java.nio.file.Paths;
|
||||
|
||||
@SpringBootApplication
|
||||
class KerberosClientApp {
|
||||
|
||||
static {
|
||||
System.setProperty("java.security.krb5.conf",
|
||||
Paths.get(".\\krb-test-workdir\\krb5.conf").normalize().toAbsolutePath().toString());
|
||||
System.setProperty("sun.security.krb5.debug", "true");
|
||||
// disable usage of local kerberos ticket cache
|
||||
System.setProperty("http.use.global.creds", "false");
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(KerberosClientApp.class, args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package kerberos.client;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
@Service
|
||||
class SampleClient {
|
||||
|
||||
@Value("${app.access-url}")
|
||||
private String endpoint;
|
||||
|
||||
private RestTemplate restTemplate;
|
||||
|
||||
public SampleClient(RestTemplate restTemplate) {
|
||||
this.restTemplate = restTemplate;
|
||||
}
|
||||
|
||||
void setRestTemplate(RestTemplate restTemplate) {
|
||||
this.restTemplate = restTemplate;
|
||||
}
|
||||
|
||||
String getData() {
|
||||
return restTemplate.getForObject(endpoint, String.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package kerberos.client.config;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
@Configuration
|
||||
@Import(KerberosConfig.class)
|
||||
class AppConfig {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package kerberos.client.config;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.kerberos.client.KerberosRestTemplate;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
@Configuration
|
||||
class KerberosConfig {
|
||||
|
||||
@Value("${app.user-principal}")
|
||||
private String principal;
|
||||
|
||||
@Value("${app.keytab-location}")
|
||||
private String keytabLocation;
|
||||
|
||||
@Bean
|
||||
public RestTemplate restTemplate() {
|
||||
return new KerberosRestTemplate(keytabLocation, principal);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package kerberos.kdc;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.springframework.security.kerberos.test.MiniKdc;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
class KerberosMiniKdc {
|
||||
|
||||
private static final String KRB_WORK_DIR = ".\\spring-security-sso\\spring-security-sso-kerberos\\krb-test-workdir";
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
String[] config = MiniKdcConfigBuilder.builder()
|
||||
.workDir(prepareWorkDir())
|
||||
.confDir("minikdc-krb5.conf")
|
||||
.keytabName("example.keytab")
|
||||
.principals("client/localhost", "HTTP/localhost")
|
||||
.build();
|
||||
|
||||
MiniKdc.main(config);
|
||||
}
|
||||
|
||||
private static String prepareWorkDir() throws IOException {
|
||||
Path dir = Paths.get(KRB_WORK_DIR);
|
||||
File directory = dir.normalize().toFile();
|
||||
|
||||
FileUtils.deleteQuietly(directory);
|
||||
FileUtils.forceMkdir(directory);
|
||||
return dir.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package kerberos.kdc;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Objects;
|
||||
|
||||
class MiniKdcConfigBuilder {
|
||||
|
||||
private String workDir;
|
||||
private String confDir;
|
||||
private String keytabName;
|
||||
private Collection<String> principals;
|
||||
|
||||
private MiniKdcConfigBuilder() {
|
||||
// desired
|
||||
}
|
||||
|
||||
static MiniKdcConfigBuilder builder() {
|
||||
return new MiniKdcConfigBuilder();
|
||||
}
|
||||
|
||||
MiniKdcConfigBuilder workDir(String workDir) {
|
||||
this.workDir = workDir;
|
||||
return this;
|
||||
}
|
||||
|
||||
MiniKdcConfigBuilder confDir(String cfg) {
|
||||
try {
|
||||
URL resource = Thread.currentThread().getContextClassLoader().getResource(cfg);
|
||||
URI uri = Objects.requireNonNull(resource).toURI();
|
||||
this.confDir = Paths.get(uri).toString();
|
||||
} catch (URISyntaxException cause) {
|
||||
throw new IllegalStateException("Could not resolve path for: " + cfg, cause);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
MiniKdcConfigBuilder keytabName(String keytabName) {
|
||||
this.keytabName = Paths.get(workDir).resolve(keytabName).toString();
|
||||
return this;
|
||||
}
|
||||
|
||||
MiniKdcConfigBuilder principals(String... principals) {
|
||||
this.principals = Arrays.asList(principals);
|
||||
return this;
|
||||
}
|
||||
|
||||
String[] build() {
|
||||
|
||||
Collection<String> miniKdcConfig = new ArrayList<>();
|
||||
|
||||
miniKdcConfig.add(workDir);
|
||||
miniKdcConfig.add(confDir);
|
||||
miniKdcConfig.add(keytabName);
|
||||
miniKdcConfig.addAll(principals);
|
||||
|
||||
return miniKdcConfig.toArray(new String[0]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package kerberos.server;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
import java.nio.file.Paths;
|
||||
|
||||
@SpringBootApplication
|
||||
public class KerberizedServerApp {
|
||||
|
||||
static {
|
||||
System.setProperty("java.security.krb5.conf",
|
||||
Paths.get(".\\spring-security-sso\\spring-security-sso-kerberos\\krb-test-workdir\\krb5.conf")
|
||||
.normalize().toAbsolutePath().toString());
|
||||
System.setProperty("sun.security.krb5.debug", "true");
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
SpringApplication.run(KerberizedServerApp.class, args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package kerberos.server.config;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
|
||||
|
||||
@Configuration
|
||||
class MvcConfig extends WebMvcConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
public void addViewControllers(ViewControllerRegistry registry) {
|
||||
registry.addViewController("/home").setViewName("home");
|
||||
registry.addViewController("/").setViewName("home");
|
||||
registry.addViewController("/hello").setViewName("hello");
|
||||
registry.addViewController("/login").setViewName("login");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package kerberos.server.config;
|
||||
|
||||
import kerberos.server.service.DummyUserDetailsService;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
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.kerberos.authentication.KerberosAuthenticationProvider;
|
||||
import org.springframework.security.kerberos.authentication.KerberosServiceAuthenticationProvider;
|
||||
import org.springframework.security.kerberos.authentication.sun.SunJaasKerberosClient;
|
||||
import org.springframework.security.kerberos.authentication.sun.SunJaasKerberosTicketValidator;
|
||||
import org.springframework.security.kerberos.web.authentication.SpnegoAuthenticationProcessingFilter;
|
||||
import org.springframework.security.kerberos.web.authentication.SpnegoEntryPoint;
|
||||
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Value("${app.service-principal}")
|
||||
private String servicePrincipal;
|
||||
|
||||
@Value("${app.keytab-location}")
|
||||
private String keytabLocation;
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http.exceptionHandling()
|
||||
.authenticationEntryPoint(spnegoEntryPoint())
|
||||
.and()
|
||||
.authorizeRequests().antMatchers("/", "/home").permitAll()
|
||||
.anyRequest().authenticated()
|
||||
.and()
|
||||
.formLogin().loginPage("/login").permitAll()
|
||||
.and()
|
||||
.logout().permitAll()
|
||||
.and()
|
||||
.addFilterBefore(spnegoAuthenticationProcessingFilter(authenticationManagerBean()),
|
||||
BasicAuthenticationFilter.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AuthenticationManager anAuthenticationManager() throws Exception {
|
||||
return authenticationManager();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth.authenticationProvider(kerberosAuthenticationProvider())
|
||||
.authenticationProvider(kerberosServiceAuthenticationProvider());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public KerberosAuthenticationProvider kerberosAuthenticationProvider() {
|
||||
KerberosAuthenticationProvider provider = new KerberosAuthenticationProvider();
|
||||
SunJaasKerberosClient client = new SunJaasKerberosClient();
|
||||
client.setDebug(true);
|
||||
provider.setKerberosClient(client);
|
||||
provider.setUserDetailsService(dummyUserDetailsService());
|
||||
return provider;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SpnegoEntryPoint spnegoEntryPoint() {
|
||||
return new SpnegoEntryPoint("/login");
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SpnegoAuthenticationProcessingFilter spnegoAuthenticationProcessingFilter(
|
||||
AuthenticationManager authenticationManager) {
|
||||
SpnegoAuthenticationProcessingFilter filter = new SpnegoAuthenticationProcessingFilter();
|
||||
filter.setAuthenticationManager(authenticationManager);
|
||||
return filter;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public KerberosServiceAuthenticationProvider kerberosServiceAuthenticationProvider() {
|
||||
KerberosServiceAuthenticationProvider provider = new KerberosServiceAuthenticationProvider();
|
||||
provider.setTicketValidator(sunJaasKerberosTicketValidator());
|
||||
provider.setUserDetailsService(dummyUserDetailsService());
|
||||
return provider;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SunJaasKerberosTicketValidator sunJaasKerberosTicketValidator() {
|
||||
SunJaasKerberosTicketValidator ticketValidator = new SunJaasKerberosTicketValidator();
|
||||
ticketValidator.setServicePrincipal(servicePrincipal);
|
||||
ticketValidator.setKeyTabLocation(new FileSystemResource(keytabLocation));
|
||||
ticketValidator.setDebug(true);
|
||||
return ticketValidator;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DummyUserDetailsService dummyUserDetailsService() {
|
||||
return new DummyUserDetailsService();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package kerberos.server.controller;
|
||||
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/endpoint")
|
||||
class SampleController {
|
||||
|
||||
@GetMapping
|
||||
String getIt() {
|
||||
return "data from kerberized server";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package kerberos.server.service;
|
||||
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
|
||||
public class DummyUserDetailsService implements UserDetailsService {
|
||||
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
||||
return new User(username, "notUsed", true, true, true, true, AuthorityUtils.createAuthorityList("ROLE_USER"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
# make sure the same data is configured in KerberosMiniKdc
|
||||
# otherwise configuration/communication error will occur
|
||||
app.service-principal=HTTP/localhost
|
||||
app.user-principal=client/localhost
|
||||
app.keytab-location=@project.basedir@\\krb-test-workdir\\example.keytab
|
||||
app.access-url=http://localhost:8080/endpoint
|
||||
@@ -0,0 +1,25 @@
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
[libdefaults]
|
||||
default_realm = {0}
|
||||
udp_preference_limit = 1
|
||||
|
||||
[realms]
|
||||
{0} = '{'
|
||||
kdc = {1}:{2}
|
||||
'}'
|
||||
@@ -0,0 +1,47 @@
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
dn: ou=users,dc=${0},dc=${1}
|
||||
objectClass: organizationalUnit
|
||||
objectClass: top
|
||||
ou: users
|
||||
|
||||
dn: uid=krbtgt,ou=users,dc=${0},dc=${1}
|
||||
objectClass: top
|
||||
objectClass: person
|
||||
objectClass: inetOrgPerson
|
||||
objectClass: krb5principal
|
||||
objectClass: krb5kdcentry
|
||||
cn: KDC Service
|
||||
sn: Service
|
||||
uid: krbtgt
|
||||
userPassword: secret
|
||||
krb5PrincipalName: krbtgt/${2}.${3}@${2}.${3}
|
||||
krb5KeyVersionNumber: 0
|
||||
|
||||
dn: uid=ldap,ou=users,dc=${0},dc=${1}
|
||||
objectClass: top
|
||||
objectClass: person
|
||||
objectClass: inetOrgPerson
|
||||
objectClass: krb5principal
|
||||
objectClass: krb5kdcentry
|
||||
cn: LDAP
|
||||
sn: Service
|
||||
uid: ldap
|
||||
userPassword: secret
|
||||
krb5PrincipalName: ldap/${4}@${2}.${3}
|
||||
krb5KeyVersionNumber: 0
|
||||
@@ -0,0 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
|
||||
>
|
||||
<head>
|
||||
<title>Spring Security Kerberos Example</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1 th:inline="text">Hello [[${#httpServletRequest.remoteUser}]]!</h1>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<title>Spring Security Kerberos Example</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Welcome!</h1>
|
||||
<p>Click <a th:href="@{/hello}">here</a> to see a greeting.</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,20 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
|
||||
>
|
||||
<head>
|
||||
<title>Spring Security Kerberos Example</title>
|
||||
</head>
|
||||
<body>
|
||||
<div th:if="${param.error}">
|
||||
Invalid username and password.
|
||||
</div>
|
||||
<div th:if="${param.logout}">
|
||||
You have been logged out.
|
||||
</div>
|
||||
<form th:action="@{/login}" method="post">
|
||||
<div><label> User Name : <input type="text" name="username"/> </label></div>
|
||||
<div><label> Password: <input type="password" name="password"/> </label></div>
|
||||
<div><input type="submit" value="Sign In"/></div>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,39 @@
|
||||
package kerberos.client;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.web.client.RestClientException;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
/**
|
||||
* Procedure to run this manual test:
|
||||
* <ol>
|
||||
* <li>Start {@code KerberosMiniKdc}</li>
|
||||
* <li>Start {@code KerberizedServerApp}</li>
|
||||
* <li>Run the test</li>
|
||||
* </ol>
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||
public class SampleClientManualTest {
|
||||
|
||||
@Autowired
|
||||
private SampleClient sampleClient;
|
||||
|
||||
@Test
|
||||
public void givenKerberizedRestTemplate_whenServiceCall_thenSuccess() {
|
||||
assertEquals("data from kerberized server", sampleClient.getData());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenRestTemplate_whenServiceCall_thenFail() {
|
||||
sampleClient.setRestTemplate(new RestTemplate());
|
||||
assertThrows(RestClientException.class, sampleClient::getData);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>spring-security-sso-ui-2</artifactId>
|
||||
<name>spring-security-sso-ui-2</name>
|
||||
<packaging>war</packaging>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>spring-security-sso</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</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-starter-security</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.security.oauth.boot</groupId>
|
||||
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
|
||||
<version>${oauth-auto.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.thymeleaf.extras</groupId>
|
||||
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.baeldung.config;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.web.context.request.RequestContextListener;
|
||||
|
||||
@SpringBootApplication
|
||||
public class UiApplication extends SpringBootServletInitializer {
|
||||
|
||||
|
||||
@Bean
|
||||
public RequestContextListener requestContextListener() {
|
||||
return new RequestContextListener();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(UiApplication.class, args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.baeldung.config;
|
||||
|
||||
import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
|
||||
|
||||
@EnableOAuth2Sso
|
||||
@Configuration
|
||||
public class UiSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
public void configure(HttpSecurity http) throws Exception {
|
||||
http.antMatcher("/**")
|
||||
.authorizeRequests()
|
||||
.antMatchers("/", "/login**")
|
||||
.permitAll()
|
||||
.anyRequest()
|
||||
.authenticated();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.baeldung.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
|
||||
import org.springframework.web.servlet.config.annotation.*;
|
||||
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
public class UiWebConfig implements WebMvcConfigurer {
|
||||
|
||||
@Bean
|
||||
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
|
||||
return new PropertySourcesPlaceholderConfigurer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configureDefaultServletHandling(final DefaultServletHandlerConfigurer configurer) {
|
||||
configurer.enable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addViewControllers(final ViewControllerRegistry registry) {
|
||||
registry.addViewController("/")
|
||||
.setViewName("forward:/index");
|
||||
registry.addViewController("/index");
|
||||
registry.addViewController("/securedPage");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
|
||||
registry.addResourceHandler("/resources/**")
|
||||
.addResourceLocations("/resources/");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
server:
|
||||
port: 8083
|
||||
servlet:
|
||||
context-path: /ui2
|
||||
session:
|
||||
cookie:
|
||||
name: UI2SESSION
|
||||
security:
|
||||
basic:
|
||||
enabled: false
|
||||
oauth2:
|
||||
client:
|
||||
clientId: SampleClientId
|
||||
clientSecret: secret
|
||||
accessTokenUri: http://localhost:8081/auth/oauth/token
|
||||
userAuthorizationUri: http://localhost:8081/auth/oauth/authorize
|
||||
resource:
|
||||
userInfoUri: http://localhost:8081/auth/user/me
|
||||
spring:
|
||||
thymeleaf:
|
||||
cache: false
|
||||
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
|
||||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
</configuration>
|
||||
@@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<title>Spring Security SSO Client 2</title>
|
||||
<link rel="stylesheet"
|
||||
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="col-sm-12">
|
||||
<h1>Spring Security SSO Client 2</h1>
|
||||
<a class="btn btn-primary" href="securedPage">Login</a>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,20 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<title>Spring Security SSO Client 2</title>
|
||||
<link rel="stylesheet"
|
||||
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="col-sm-12">
|
||||
<h1>Secured Page</h1>
|
||||
Welcome, <span th:text="${#authentication.name}">Name</span>
|
||||
<br/>
|
||||
Your authorities are <span th:text="${#authentication.authorities}">authorities</span>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.baeldung;
|
||||
|
||||
import com.baeldung.config.UiApplication;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = UiApplication.class, webEnvironment = WebEnvironment.RANDOM_PORT)
|
||||
public class SpringContextTest {
|
||||
|
||||
@Test
|
||||
public void whenLoadApplication_thenSuccess() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>spring-security-sso-ui</artifactId>
|
||||
<name>spring-security-sso-ui</name>
|
||||
<packaging>war</packaging>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>spring-security-sso</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</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-starter-security</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.security.oauth.boot</groupId>
|
||||
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
|
||||
<version>${oauth-auto.version}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.thymeleaf.extras</groupId>
|
||||
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.baeldung.config;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.web.context.request.RequestContextListener;
|
||||
|
||||
|
||||
@SpringBootApplication
|
||||
public class UiApplication extends SpringBootServletInitializer {
|
||||
|
||||
@Bean
|
||||
public RequestContextListener requestContextListener() {
|
||||
return new RequestContextListener();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(UiApplication.class, args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.baeldung.config;
|
||||
|
||||
import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
|
||||
|
||||
@EnableOAuth2Sso
|
||||
@Configuration
|
||||
public class UiSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
public void configure(HttpSecurity http) throws Exception {
|
||||
http.antMatcher("/**")
|
||||
.authorizeRequests()
|
||||
.antMatchers("/", "/login**")
|
||||
.permitAll()
|
||||
.anyRequest()
|
||||
.authenticated();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.baeldung.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
|
||||
import org.springframework.web.servlet.config.annotation.*;
|
||||
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
public class UiWebConfig implements WebMvcConfigurer {
|
||||
|
||||
@Bean
|
||||
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
|
||||
return new PropertySourcesPlaceholderConfigurer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configureDefaultServletHandling(final DefaultServletHandlerConfigurer configurer) {
|
||||
configurer.enable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addViewControllers(final ViewControllerRegistry registry) {
|
||||
registry.addViewController("/")
|
||||
.setViewName("forward:/index");
|
||||
registry.addViewController("/index");
|
||||
registry.addViewController("/securedPage");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
|
||||
registry.addResourceHandler("/resources/**")
|
||||
.addResourceLocations("/resources/");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
server:
|
||||
port: 8082
|
||||
servlet:
|
||||
context-path: /ui
|
||||
session:
|
||||
cookie:
|
||||
name: UISESSION
|
||||
security:
|
||||
basic:
|
||||
enabled: false
|
||||
oauth2:
|
||||
client:
|
||||
clientId: SampleClientId
|
||||
clientSecret: secret
|
||||
accessTokenUri: http://localhost:8081/auth/oauth/token
|
||||
userAuthorizationUri: http://localhost:8081/auth/oauth/authorize
|
||||
resource:
|
||||
userInfoUri: http://localhost:8081/auth/user/me
|
||||
spring:
|
||||
thymeleaf:
|
||||
cache: false
|
||||
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
|
||||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
</configuration>
|
||||
@@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<title>Spring Security SSO</title>
|
||||
<link rel="stylesheet"
|
||||
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="col-sm-12">
|
||||
<h1>Spring Security SSO</h1>
|
||||
<a class="btn btn-primary" href="securedPage">Login</a>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<title>Spring Security SSO</title>
|
||||
<link rel="stylesheet"
|
||||
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="col-sm-12">
|
||||
<h1>Secured Page</h1>
|
||||
Welcome, <span th:text="${#authentication.name}">Name</span>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.baeldung;
|
||||
|
||||
import com.baeldung.config.UiApplication;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = UiApplication.class, webEnvironment = WebEnvironment.RANDOM_PORT)
|
||||
public class SpringContextTest {
|
||||
|
||||
@Test
|
||||
public void whenLoadApplication_thenSuccess() {
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user