springSecurity使用

官网//spring.io/guides/gs/securing-web/
无情的翻译官。。。。。。

1.1 依赖包导入

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="//maven.apache.org/POM/4.0.0" xmlns:xsi="//www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="//maven.apache.org/POM/4.0.0 //maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.2.2.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>securing-web</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>securing-web</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</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-security</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-test</artifactId>
			<scope>test</scope>
		</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>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

里面引入了测试要用到的web模块,thymeleaf引擎模块,以及咱们的security模块

2.1 没有安全机制下的一个web

测试的项目有两个页面home.html和hello.html

src/main/resources/templates/home.html:

<!DOCTYPE html>
<html xmlns="//www.w3.org/1999/xhtml" xmlns:th="//www.thymeleaf.org" xmlns:sec="//www.thymeleaf.org/thymeleaf-extras-springsecurity3">
    <head>
        <title>Spring Security Example</title>
    </head>
    <body>
        <h1>Welcome!</h1>

        <p>Click <a th:href="@{/hello}">here</a> to see a greeting.</p>
    </body>
</html>

home页面提交到一个/hello请求,会返回一个hello.html:

src/main/resources/templates/hello.html:

<!DOCTYPE html>
<html xmlns="//www.w3.org/1999/xhtml" xmlns:th="//www.thymeleaf.org"
      xmlns:sec="//www.thymeleaf.org/thymeleaf-extras-springsecurity3">
    <head>
        <title>Hello World!</title>
    </head>
    <body>
        <h1>Hello world!</h1>
    </body>
</html>

这个web项目依赖于springmvc,我们可以自定义一下视图解析器:

src/main/java/com/example/securingweb/MvcConfig.java:

package com.example.securingweb;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class MvcConfig implements WebMvcConfigurer {

	public void addViewControllers(ViewControllerRegistry registry) {
		registry.addViewController("/home").setViewName("home");
		registry.addViewController("/").setViewName("home");
		registry.addViewController("/hello").setViewName("hello");
		registry.addViewController("/login").setViewName("login");
	}

}

这种无安全机制的web任何人都可以通过localhost:8080/hello 直接访问到hello.html.
假设我们要防止那些没有经过授权的用户进入到hello.html页面,就需要用到我们的security模块。

3.1 做一个安全机制的web

在引入了我们的security包的情况下,我们需要自定义下我们的安全规则;

src/main/java/com/example/securingweb/WebSecurityConfig.java:

package com.example.securingweb;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
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.provisioning.InMemoryUserDetailsManager;

@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
	@Override
	public UserDetailsService userDetailsService() {
		UserDetails user =
			 User.withDefaultPasswordEncoder()
				.username("user")
				.password("password")
				.roles("USER")
				.build();

		return new InMemoryUserDetailsManager(user);
	}
}
  • @EnableWebSecurity:用于开启springSecurity模块功能和提供与springmvc集成的功能
  • WebSecurityConfigurerAdapter:自定义的配置都要继承这个类
  • configure(HttpSecurity):定义了哪些http请求需要被安全加密,哪些可以被放行通过。这里”/”,”home”这两个路径不需要任何授权请求,也就是说任何人都可以访问。这里注意链式写法用.and()衔接。
  • formLogin()和logout()这两个一般都是单独定制,对于formLogin()我们把它转向到我们自己写的login页面,否则SpringSecurity在拦截到一个非法请求的时候会返回你一个自带的login页面。当然对于这两个页面我们都是对放行的。
  • userDetailsService() :定义了一个内存对象,这里注意withDefaultPasswordEncoder(),高版本的SpringSecurity已经不允许明码形式的密码,必须对密码进行加密再传送。

src/main/resources/templates/login.html:

<!DOCTYPE html>
<html xmlns="//www.w3.org/1999/xhtml" xmlns:th="//www.thymeleaf.org"
      xmlns:sec="//www.thymeleaf.org/thymeleaf-extras-springsecurity3">
    <head>
        <title>Spring Security 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>

src/main/resources/templates/hello.html:

<!DOCTYPE html>
<html xmlns="//www.w3.org/1999/xhtml" xmlns:th="//www.thymeleaf.org"
      xmlns:sec="//www.thymeleaf.org/thymeleaf-extras-springsecurity3">
    <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>