15 changed files with 509 additions and 2 deletions
@ -0,0 +1,5 @@
@@ -0,0 +1,5 @@
|
||||
apply plugin: 'spring-boot' |
||||
|
||||
sonarqube { |
||||
skipProject = true |
||||
} |
||||
@ -0,0 +1,16 @@
@@ -0,0 +1,16 @@
|
||||
apply from: BOOT_SAMPLE_GRADLE |
||||
|
||||
springBoot { |
||||
mainClass = 'org.springframework.security.samples.HelloWorldApplication' |
||||
} |
||||
|
||||
dependencies { |
||||
compile "org.springframework.boot:spring-boot-starter-web", |
||||
"org.springframework.boot:spring-boot-starter-thymeleaf", |
||||
"org.thymeleaf.extras:thymeleaf-extras-springsecurity4:2.1.2.RELEASE", |
||||
project(":spring-security-config"), |
||||
project(":spring-security-web") |
||||
|
||||
testCompile "org.springframework.boot:spring-boot-starter-test", |
||||
project(":spring-security-test") |
||||
} |
||||
@ -0,0 +1,144 @@
@@ -0,0 +1,144 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> |
||||
<modelVersion>4.0.0</modelVersion> |
||||
<groupId>org.springframework.security</groupId> |
||||
<artifactId>spring-security-samples-boot-helloworld</artifactId> |
||||
<version>4.1.0.BUILD-SNAPSHOT</version> |
||||
<name>spring-security-samples-boot-helloworld</name> |
||||
<description>spring-security-samples-boot-helloworld</description> |
||||
<url>http://spring.io/spring-security</url> |
||||
<organization> |
||||
<name>spring.io</name> |
||||
<url>http://spring.io/</url> |
||||
</organization> |
||||
<licenses> |
||||
<license> |
||||
<name>The Apache Software License, Version 2.0</name> |
||||
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url> |
||||
<distribution>repo</distribution> |
||||
</license> |
||||
</licenses> |
||||
<developers> |
||||
<developer> |
||||
<id>rwinch</id> |
||||
<name>Rob Winch</name> |
||||
<email>rwinch@gopivotal.com</email> |
||||
</developer> |
||||
</developers> |
||||
<scm> |
||||
<connection>scm:git:git://github.com/spring-projects/spring-security</connection> |
||||
<developerConnection>scm:git:git://github.com/spring-projects/spring-security</developerConnection> |
||||
<url>https://github.com/spring-projects/spring-security</url> |
||||
</scm> |
||||
<dependencyManagement> |
||||
<dependencies> |
||||
<dependency> |
||||
<groupId>org.springframework</groupId> |
||||
<artifactId>spring-framework-bom</artifactId> |
||||
<version>4.2.5.RELEASE</version> |
||||
<type>pom</type> |
||||
<scope>import</scope> |
||||
</dependency> |
||||
</dependencies> |
||||
</dependencyManagement> |
||||
<dependencies> |
||||
<dependency> |
||||
<groupId>org.springframework.boot</groupId> |
||||
<artifactId>spring-boot-starter-thymeleaf</artifactId> |
||||
<scope>compile</scope> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>org.springframework.boot</groupId> |
||||
<artifactId>spring-boot-starter-web</artifactId> |
||||
<scope>compile</scope> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>org.springframework.security</groupId> |
||||
<artifactId>spring-security-config</artifactId> |
||||
<version>4.1.0.BUILD-SNAPSHOT</version> |
||||
<scope>compile</scope> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>org.springframework.security</groupId> |
||||
<artifactId>spring-security-web</artifactId> |
||||
<version>4.1.0.BUILD-SNAPSHOT</version> |
||||
<scope>compile</scope> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>org.thymeleaf.extras</groupId> |
||||
<artifactId>thymeleaf-extras-springsecurity4</artifactId> |
||||
<version>2.1.2.RELEASE</version> |
||||
<scope>compile</scope> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>commons-logging</groupId> |
||||
<artifactId>commons-logging</artifactId> |
||||
<version>1.2</version> |
||||
<scope>compile</scope> |
||||
<optional>true</optional> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>ch.qos.logback</groupId> |
||||
<artifactId>logback-classic</artifactId> |
||||
<version>1.1.2</version> |
||||
<scope>test</scope> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>junit</groupId> |
||||
<artifactId>junit</artifactId> |
||||
<version>4.12</version> |
||||
<scope>test</scope> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>org.assertj</groupId> |
||||
<artifactId>assertj-core</artifactId> |
||||
<version>2.2.0</version> |
||||
<scope>test</scope> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>org.mockito</groupId> |
||||
<artifactId>mockito-core</artifactId> |
||||
<version>1.10.19</version> |
||||
<scope>test</scope> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>org.slf4j</groupId> |
||||
<artifactId>jcl-over-slf4j</artifactId> |
||||
<version>1.7.7</version> |
||||
<scope>test</scope> |
||||
</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> |
||||
<version>4.1.0.BUILD-SNAPSHOT</version> |
||||
<scope>test</scope> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>org.springframework</groupId> |
||||
<artifactId>spring-test</artifactId> |
||||
<scope>test</scope> |
||||
</dependency> |
||||
</dependencies> |
||||
<repositories> |
||||
<repository> |
||||
<id>spring-snapshot</id> |
||||
<url>https://repo.spring.io/snapshot</url> |
||||
</repository> |
||||
</repositories> |
||||
<build> |
||||
<plugins> |
||||
<plugin> |
||||
<artifactId>maven-compiler-plugin</artifactId> |
||||
<configuration> |
||||
<source>1.7</source> |
||||
<target>1.7</target> |
||||
</configuration> |
||||
</plugin> |
||||
</plugins> |
||||
</build> |
||||
</project> |
||||
@ -0,0 +1,120 @@
@@ -0,0 +1,120 @@
|
||||
/* |
||||
* Copyright 2012-2016 the original author or authors. |
||||
* |
||||
* Licensed 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. |
||||
*/ |
||||
package org.springframework.security.samples; |
||||
|
||||
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.SpringApplicationConfiguration; |
||||
import org.springframework.mock.web.MockHttpSession; |
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; |
||||
import org.springframework.test.context.web.WebAppConfiguration; |
||||
import org.springframework.test.web.servlet.MockMvc; |
||||
import org.springframework.test.web.servlet.MvcResult; |
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders; |
||||
import org.springframework.web.context.WebApplicationContext; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.formLogin; |
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; |
||||
import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated; |
||||
import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.unauthenticated; |
||||
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.status; |
||||
|
||||
/** |
||||
* |
||||
* @author Joe Grandja |
||||
*/ |
||||
@RunWith(SpringJUnit4ClassRunner.class) |
||||
@SpringApplicationConfiguration(HelloWorldApplication.class) |
||||
@WebAppConfiguration |
||||
public class HelloWorldApplicationTests { |
||||
|
||||
@Autowired |
||||
private WebApplicationContext context; |
||||
|
||||
private MockMvc mockMvc; |
||||
|
||||
@Before |
||||
public void setup() { |
||||
mockMvc = MockMvcBuilders |
||||
.webAppContextSetup(context) |
||||
.apply(springSecurity()) |
||||
.build(); |
||||
} |
||||
|
||||
@Test |
||||
public void accessUnprotected() throws Exception { |
||||
this.mockMvc.perform(get("/index")).andExpect(status().isOk()); |
||||
} |
||||
|
||||
@Test |
||||
public void accessProtectedRedirectsToLogin() throws Exception { |
||||
MvcResult mvcResult = this.mockMvc.perform(get("/user/index")) |
||||
.andExpect(status().is3xxRedirection()) |
||||
.andReturn(); |
||||
|
||||
assertThat(mvcResult.getResponse().getRedirectedUrl()).endsWith("/login"); |
||||
} |
||||
|
||||
@Test |
||||
public void loginUser() throws Exception { |
||||
this.mockMvc.perform(formLogin().user("user1").password("password1")) |
||||
.andExpect(authenticated()); |
||||
} |
||||
|
||||
@Test |
||||
public void loginInvalidUser() throws Exception { |
||||
this.mockMvc.perform(formLogin().user("invalid").password("invalid")) |
||||
.andExpect(unauthenticated()) |
||||
.andExpect(status().is3xxRedirection()); |
||||
} |
||||
|
||||
@Test |
||||
public void loginUserAccessProtected() throws Exception { |
||||
MvcResult mvcResult = this.mockMvc.perform(formLogin().user("user1").password("password1")) |
||||
.andExpect(authenticated()) |
||||
.andReturn(); |
||||
|
||||
MockHttpSession httpSession = MockHttpSession.class.cast(mvcResult.getRequest().getSession(false)); |
||||
|
||||
this.mockMvc.perform(get("/user/index") |
||||
.session(httpSession)) |
||||
.andExpect(status().isOk()); |
||||
} |
||||
|
||||
@Test |
||||
public void loginUserValidateLogout() throws Exception { |
||||
MvcResult mvcResult = this.mockMvc.perform(formLogin().user("user1").password("password1")) |
||||
.andExpect(authenticated()) |
||||
.andReturn(); |
||||
|
||||
MockHttpSession httpSession = MockHttpSession.class.cast(mvcResult.getRequest().getSession(false)); |
||||
|
||||
this.mockMvc.perform(post("/logout").with(csrf()) |
||||
.session(httpSession)) |
||||
.andExpect(unauthenticated()); |
||||
|
||||
this.mockMvc.perform(get("/user/index") |
||||
.session(httpSession)) |
||||
.andExpect(unauthenticated()) |
||||
.andExpect(status().is3xxRedirection()); |
||||
} |
||||
} |
||||
@ -0,0 +1,32 @@
@@ -0,0 +1,32 @@
|
||||
/* |
||||
* Copyright 2012-2016 the original author or authors. |
||||
* |
||||
* Licensed 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. |
||||
*/ |
||||
package org.springframework.security.samples; |
||||
|
||||
import org.springframework.boot.SpringApplication; |
||||
import org.springframework.boot.autoconfigure.SpringBootApplication; |
||||
|
||||
/** |
||||
* @author Joe Grandja |
||||
*/ |
||||
@SpringBootApplication |
||||
public class HelloWorldApplication { |
||||
|
||||
public static void main(String[] args) { |
||||
SpringApplication.run(HelloWorldApplication.class, args); |
||||
} |
||||
|
||||
|
||||
} |
||||
@ -0,0 +1,50 @@
@@ -0,0 +1,50 @@
|
||||
/* |
||||
* Copyright 2002-2016 the original author or authors. |
||||
* |
||||
* Licensed 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. |
||||
*/ |
||||
package org.springframework.security.samples.config; |
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
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; |
||||
|
||||
/** |
||||
* @author Joe Grandja |
||||
*/ |
||||
@EnableWebSecurity |
||||
public class SecurityConfig extends WebSecurityConfigurerAdapter { |
||||
|
||||
// @formatter:off
|
||||
@Override |
||||
protected void configure(HttpSecurity http) throws Exception { |
||||
http |
||||
.authorizeRequests() |
||||
.antMatchers("/css/**", "/index").permitAll() |
||||
.antMatchers("/user/**").hasRole("USER") |
||||
.and() |
||||
.formLogin().loginPage("/login").failureUrl("/login-error"); |
||||
} |
||||
// @formatter:on
|
||||
|
||||
// @formatter:off
|
||||
@Autowired |
||||
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { |
||||
auth |
||||
.inMemoryAuthentication() |
||||
.withUser("user1").password("password1").roles("USER"); |
||||
} |
||||
// @formatter:on
|
||||
} |
||||
@ -0,0 +1,54 @@
@@ -0,0 +1,54 @@
|
||||
/* |
||||
* Copyright 2002-2016 the original author or authors. |
||||
* |
||||
* Licensed 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. |
||||
*/ |
||||
package org.springframework.security.samples.web; |
||||
|
||||
import org.springframework.stereotype.Controller; |
||||
import org.springframework.ui.Model; |
||||
import org.springframework.web.bind.annotation.RequestMapping; |
||||
|
||||
/** |
||||
* @author Joe Grandja |
||||
*/ |
||||
@Controller |
||||
public class MainController { |
||||
|
||||
@RequestMapping("/") |
||||
public String root() { |
||||
return "redirect:/index"; |
||||
} |
||||
|
||||
@RequestMapping("/index") |
||||
public String index() { |
||||
return "index"; |
||||
} |
||||
|
||||
@RequestMapping("/user/index") |
||||
public String userIndex() { |
||||
return "user/index"; |
||||
} |
||||
|
||||
@RequestMapping("/login") |
||||
public String login() { |
||||
return "login"; |
||||
} |
||||
|
||||
@RequestMapping("/login-error") |
||||
public String loginError(Model model) { |
||||
model.addAttribute("loginError", true); |
||||
return "login"; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,12 @@
@@ -0,0 +1,12 @@
|
||||
server: |
||||
port: 8080 |
||||
|
||||
logging: |
||||
level: |
||||
root: WARN |
||||
org.springframework.web: INFO |
||||
org.springframework.security: INFO |
||||
|
||||
spring: |
||||
thymeleaf: |
||||
cache: true |
||||
@ -0,0 +1,13 @@
@@ -0,0 +1,13 @@
|
||||
body { |
||||
font-family: sans; |
||||
font-size: 1em; |
||||
} |
||||
|
||||
p.error { |
||||
font-weight: bold; |
||||
color: red; |
||||
} |
||||
|
||||
div.logout { |
||||
float: right; |
||||
} |
||||
@ -0,0 +1,25 @@
@@ -0,0 +1,25 @@
|
||||
<!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>Hello Spring Security</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> | |
||||
Roles: <span sec:authentication="principal.authorities"></span> |
||||
<div> |
||||
<form action="/logout" method="post"> |
||||
<input type="submit" value="Logout" /> |
||||
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" /> |
||||
</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> |
||||
@ -0,0 +1,21 @@
@@ -0,0 +1,21 @@
|
||||
<!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: user1 / password1</p> |
||||
<p th:if="${loginError}" class="error">Wrong user or password</p> |
||||
<form th:action="@{/login}" method="post"> |
||||
<label for="username">Username</label>: |
||||
<input type="text" id="username" name="username" autofocus="autofocus" /> <br /> |
||||
<label for="password">Password</label>: |
||||
<input 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> |
||||
@ -0,0 +1,13 @@
@@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html> |
||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"> |
||||
<head> |
||||
<title>Hello Spring Security</title> |
||||
<meta charset="utf-8" /> |
||||
<link rel="stylesheet" href="/css/main.css" th:href="@{/css/main.css}" /> |
||||
</head> |
||||
<body> |
||||
<div th:substituteby="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> |
||||
Loading…
Reference in new issue