springboot安全
基于springmvc的springboot security
我们会用代码看看spring-security如何在boot中工作。
没有spring-security依赖的情况:
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.ocean</groupId>
<artifactId>springbootTutorial</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>springbootTutorial</name>
<url>http://maven.apache.org</url>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.4.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
我们将在mvc配置中配置一些不经过controller的url映射:
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@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");
}
}
这些路径可以不经过controller直接访问。
比如/home
对应的home.html
:
<!DOCTYPE html>
<html lang="en" xmlns:th="https://www.thymeleaf.org" >
<head>
<meta charset="UTF-8">
<title>spring security</title>
</head>
<body>
<p>Click <a th:href="@{/hello}">here</a> to see a greeting.</p>
</body>
</html>
显然。这是不安全的。
为此,我们uncomment掉security的依赖。
并且用代码配置:
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().
antMatchers("/","/home").permitAll()
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
@Bean
public UserDetailsService userDetailsService(){
UserDetails user = User.withDefaultPasswordEncoder()
.username("user")
.password("password")
.roles("USER")
.build();
return new InMemoryUserDetailsManager(user);
}
}
我们注入了一个UserDetailsService
,它可以加载特定用户的信息。
我们采用基于内存的用户存储方式(InMemoryUserDetailsManager
),也就是,它是非持久化的,仅用于测试的。
这里创建的user的username为user
,password为password
,角色是USER
,使用默认的密码加密器。
antMatchers("/","/home").permitAll()
表示url路径为/
或者/home
是不需要安全认证的。
.anyRequest().authenticated()
表示除此以外的其他路径都要认证。
并且,我们准备了自定义的登陆页面,登陆登出也是任何人可以执行的操作。
我已经给出了home.html
,我们想通过超链接访问hello.html
:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org"
>
<head>
<title>Hello World!</title>
</head>
<body>
<h1 th:inline="text">Hello [[${#httpServletRequest.remoteUser}]]!</h1>
<form th:action="@{/logout}" method="post">
<input type="submit" value="Sign Out"/>
</form>
</body>
</html>
但是之前我们需要经过login的认证(login.html
):
<!DOCTYPE html>
<html lang="en" xmlns:th="https://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>LOG IN</title>
</head>
<body>
<div th:if="${param.error}">Invalid username or 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="LOG IN"></div>
</form>
</body>
</html>
测试:
主页:
登陆出错:
登陆成功。
登出。