From 3c769436274858563d2196d83c8ccd57d2d0c42f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20R=C3=A4del?= Date: Mon, 8 Aug 2016 01:55:42 +0200 Subject: [PATCH] Added second version to authenticate with client certificates. --- .../spring/security/x509/UserController.java | 2 + .../x509/X509AuthenticationServer.java | 39 ++++++++++++++- .../src/main/resources/application.properties | 5 +- .../{server => client-auth-server}/pom.xml | 6 +-- .../spring/security/x509/UserController.java | 5 +- .../x509/X509AuthenticationServer.java | 47 +++++++++++++++++++ .../src/main/resources/application.properties | 7 ++- .../src/main/resources/templates/user.html | 4 +- .../x509/X509AuthenticationServerTests.java | 2 - spring-security-x509/keystore/Makefile | 6 +++ .../x509/X509AuthenticationServer.java | 12 ----- 11 files changed, 110 insertions(+), 25 deletions(-) rename spring-security-x509/{server => client-auth-server}/pom.xml (92%) rename spring-security-x509/{server => client-auth-server}/src/main/java/com/baeldung/spring/security/x509/UserController.java (82%) create mode 100644 spring-security-x509/client-auth-server/src/main/java/com/baeldung/spring/security/x509/X509AuthenticationServer.java rename spring-security-x509/{server => client-auth-server}/src/main/resources/application.properties (50%) rename spring-security-x509/{server => client-auth-server}/src/main/resources/templates/user.html (51%) rename spring-security-x509/{server => client-auth-server}/src/test/java/com/baeldung/spring/security/x509/X509AuthenticationServerTests.java (99%) delete mode 100644 spring-security-x509/server/src/main/java/com/baeldung/spring/security/x509/X509AuthenticationServer.java diff --git a/spring-security-x509/basic-secured-server/src/main/java/com/baeldung/spring/security/x509/UserController.java b/spring-security-x509/basic-secured-server/src/main/java/com/baeldung/spring/security/x509/UserController.java index dfe000a3d0..af1c103739 100644 --- a/spring-security-x509/basic-secured-server/src/main/java/com/baeldung/spring/security/x509/UserController.java +++ b/spring-security-x509/basic-secured-server/src/main/java/com/baeldung/spring/security/x509/UserController.java @@ -1,5 +1,6 @@ package com.baeldung.spring.security.x509; +import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.core.Authentication; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.stereotype.Controller; @@ -10,6 +11,7 @@ import java.security.Principal; @Controller public class UserController { + @PreAuthorize("hasAuthority('ROLE_USER')") @RequestMapping(value = "/user") public String user(Model model, Principal principal) { UserDetails currentUser = (UserDetails) ((Authentication) principal).getPrincipal(); diff --git a/spring-security-x509/basic-secured-server/src/main/java/com/baeldung/spring/security/x509/X509AuthenticationServer.java b/spring-security-x509/basic-secured-server/src/main/java/com/baeldung/spring/security/x509/X509AuthenticationServer.java index 02a3bf45d6..41e88686fb 100644 --- a/spring-security-x509/basic-secured-server/src/main/java/com/baeldung/spring/security/x509/X509AuthenticationServer.java +++ b/spring-security-x509/basic-secured-server/src/main/java/com/baeldung/spring/security/x509/X509AuthenticationServer.java @@ -1,11 +1,48 @@ package com.baeldung.spring.security.x509; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.builders.WebSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +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; @SpringBootApplication -public class X509AuthenticationServer { +@EnableWebSecurity +@EnableGlobalMethodSecurity(prePostEnabled = true) +public class X509AuthenticationServer extends WebSecurityConfigurerAdapter { + public static void main(String[] args) { SpringApplication.run(X509AuthenticationServer.class, args); } + + @Override + protected void configure(HttpSecurity http) throws Exception { + http.authorizeRequests().anyRequest().authenticated() + .and() + .x509().subjectPrincipalRegex("CN=(.*?)(?:,|$)").userDetailsService(userDetailsService()); + } + + @Bean + public UserDetailsService userDetailsService() { + return new UserDetailsService() { + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + if (username.equals("cid")) { + return new User(username, "", AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER")); + } + throw new UsernameNotFoundException("User not found!"); + } + }; + } } diff --git a/spring-security-x509/basic-secured-server/src/main/resources/application.properties b/spring-security-x509/basic-secured-server/src/main/resources/application.properties index 1eed9cbbb0..294c7d9c6b 100644 --- a/spring-security-x509/basic-secured-server/src/main/resources/application.properties +++ b/spring-security-x509/basic-secured-server/src/main/resources/application.properties @@ -5,4 +5,7 @@ server.ssl.key-password=${PASSWORD} server.ssl.enabled=true server.port=8443 security.user.name=Admin -security.user.password=admin \ No newline at end of file +security.user.password=admin +server.ssl.trust-store=../keystore/truststore.jks +server.ssl.trust-store-password=${PASSWORD} +server.ssl.client-auth=need \ No newline at end of file diff --git a/spring-security-x509/server/pom.xml b/spring-security-x509/client-auth-server/pom.xml similarity index 92% rename from spring-security-x509/server/pom.xml rename to spring-security-x509/client-auth-server/pom.xml index eabd0364ef..8b902ee63f 100644 --- a/spring-security-x509/server/pom.xml +++ b/spring-security-x509/client-auth-server/pom.xml @@ -4,12 +4,12 @@ 4.0.0 com.baeldung.spring.security - server + client-auth-server 0.0.1-SNAPSHOT jar - server - Spring x.509 Authentication Demo + client-auth-server + Spring x.509 Client Authentication Demo org.springframework.boot diff --git a/spring-security-x509/server/src/main/java/com/baeldung/spring/security/x509/UserController.java b/spring-security-x509/client-auth-server/src/main/java/com/baeldung/spring/security/x509/UserController.java similarity index 82% rename from spring-security-x509/server/src/main/java/com/baeldung/spring/security/x509/UserController.java rename to spring-security-x509/client-auth-server/src/main/java/com/baeldung/spring/security/x509/UserController.java index 90c8897d8f..af1c103739 100644 --- a/spring-security-x509/server/src/main/java/com/baeldung/spring/security/x509/UserController.java +++ b/spring-security-x509/client-auth-server/src/main/java/com/baeldung/spring/security/x509/UserController.java @@ -1,5 +1,6 @@ package com.baeldung.spring.security.x509; +import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.core.Authentication; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.stereotype.Controller; @@ -9,8 +10,8 @@ import org.springframework.web.bind.annotation.RequestMapping; import java.security.Principal; @Controller -public class UserResource { - +public class UserController { + @PreAuthorize("hasAuthority('ROLE_USER')") @RequestMapping(value = "/user") public String user(Model model, Principal principal) { UserDetails currentUser = (UserDetails) ((Authentication) principal).getPrincipal(); diff --git a/spring-security-x509/client-auth-server/src/main/java/com/baeldung/spring/security/x509/X509AuthenticationServer.java b/spring-security-x509/client-auth-server/src/main/java/com/baeldung/spring/security/x509/X509AuthenticationServer.java new file mode 100644 index 0000000000..462c984555 --- /dev/null +++ b/spring-security-x509/client-auth-server/src/main/java/com/baeldung/spring/security/x509/X509AuthenticationServer.java @@ -0,0 +1,47 @@ +package com.baeldung.spring.security.x509; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.builders.WebSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +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; + +@SpringBootApplication +@EnableWebSecurity +@EnableGlobalMethodSecurity(prePostEnabled = true) +public class X509AuthenticationServer extends WebSecurityConfigurerAdapter { + public static void main(String[] args) { + SpringApplication.run(X509AuthenticationServer.class, args); + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + http.authorizeRequests().anyRequest().authenticated() + .and() + .x509().subjectPrincipalRegex("CN=(.*?)(?:,|$)").userDetailsService(userDetailsService()); + } + + @Bean + public UserDetailsService userDetailsService() { + return new UserDetailsService() { + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + if (username.equals("cid")) { + return new User(username, "", AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER")); + } + throw new UsernameNotFoundException("User not found!"); + } + }; + } +} diff --git a/spring-security-x509/server/src/main/resources/application.properties b/spring-security-x509/client-auth-server/src/main/resources/application.properties similarity index 50% rename from spring-security-x509/server/src/main/resources/application.properties rename to spring-security-x509/client-auth-server/src/main/resources/application.properties index 89a234b1ac..294c7d9c6b 100644 --- a/spring-security-x509/server/src/main/resources/application.properties +++ b/spring-security-x509/client-auth-server/src/main/resources/application.properties @@ -1,8 +1,11 @@ server.ssl.key-store=../keystore/keystore.jks server.ssl.key-store-password=${PASSWORD} -server.ssl.key-alias=localhost +server.ssl.key-alias=${HOSTNAME} server.ssl.key-password=${PASSWORD} server.ssl.enabled=true server.port=8443 security.user.name=Admin -security.user.password=admin \ No newline at end of file +security.user.password=admin +server.ssl.trust-store=../keystore/truststore.jks +server.ssl.trust-store-password=${PASSWORD} +server.ssl.client-auth=need \ No newline at end of file diff --git a/spring-security-x509/server/src/main/resources/templates/user.html b/spring-security-x509/client-auth-server/src/main/resources/templates/user.html similarity index 51% rename from spring-security-x509/server/src/main/resources/templates/user.html rename to spring-security-x509/client-auth-server/src/main/resources/templates/user.html index 0be84680fe..a04ec6b406 100644 --- a/spring-security-x509/server/src/main/resources/templates/user.html +++ b/spring-security-x509/client-auth-server/src/main/resources/templates/user.html @@ -1,9 +1,9 @@ - X.509 Authentication Demo +X.509 Authentication Demo -

Hello !

+

Hello !

\ No newline at end of file diff --git a/spring-security-x509/server/src/test/java/com/baeldung/spring/security/x509/X509AuthenticationServerTests.java b/spring-security-x509/client-auth-server/src/test/java/com/baeldung/spring/security/x509/X509AuthenticationServerTests.java similarity index 99% rename from spring-security-x509/server/src/test/java/com/baeldung/spring/security/x509/X509AuthenticationServerTests.java rename to spring-security-x509/client-auth-server/src/test/java/com/baeldung/spring/security/x509/X509AuthenticationServerTests.java index f08916c80b..0b9a11552a 100644 --- a/spring-security-x509/server/src/test/java/com/baeldung/spring/security/x509/X509AuthenticationServerTests.java +++ b/spring-security-x509/client-auth-server/src/test/java/com/baeldung/spring/security/x509/X509AuthenticationServerTests.java @@ -8,9 +8,7 @@ import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest public class X509AuthenticationServerTests { - @Test public void contextLoads() { } - } diff --git a/spring-security-x509/keystore/Makefile b/spring-security-x509/keystore/Makefile index 7f0c5e3077..5321be9de3 100644 --- a/spring-security-x509/keystore/Makefile +++ b/spring-security-x509/keystore/Makefile @@ -2,6 +2,7 @@ PASSWORD=changeit KEYSTORE=keystore.jks HOSTNAME=localhost CLIENTNAME=cid + # CN = Common Name # OU = Organization Unit # O = Organization Name @@ -76,6 +77,11 @@ add-client: keytool -import -trustcacerts -alias $(CLIENTNAME) \ -file "$(CLIENTNAME).crt" \ -keystore $(TRUSTSTORE) -storepass $(PASSWORD) + # Export private certificate for importing into a browser + keytool -importkeystore -srcalias $(CLIENTNAME) \ + -srckeystore $(TRUSTSTORE) -srcstorepass $(PASSWORD) \ + -destkeystore "$(CLIENTNAME).p12" -deststorepass $(PASSWORD) \ + -deststoretype PKCS12 clean: # Remove generated artifacts diff --git a/spring-security-x509/server/src/main/java/com/baeldung/spring/security/x509/X509AuthenticationServer.java b/spring-security-x509/server/src/main/java/com/baeldung/spring/security/x509/X509AuthenticationServer.java deleted file mode 100644 index ab7719df0f..0000000000 --- a/spring-security-x509/server/src/main/java/com/baeldung/spring/security/x509/X509AuthenticationServer.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.baeldung.spring.security.x509; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class X509AuthenticationServer { - - public static void main(String[] args) { - SpringApplication.run(X509AuthenticationServer.class, args); - } -}