SpringBoot(2)集成Spring Security 5.0.11 入门示例

Security 简介

在JAVA WEB开发中,对web资源进行进行保护,使用filter可以说是最好的办法了,我们可以在filter中判断用户是否认证,同时我们也可以在filter中获取用户访问资源权限信息结合不同请求URL判断用户是否有权限访问WEB资源。在这个Spring Security框架的基本原理,是通过一系列有序的过滤器来实现用户认证和授予权限,从而实现安全。认证(authentication)和授权(authorization)。认证是来识别当前用户是谁的过程,授权是判断当前用户是否有权限进行相关操作的过程。

我的环境

  • SpringBoot 2.1.3
  • JDK1.8
  • Eclipse
  • Maven3.5.4
  • Windows10

项目依赖pom.xml

<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>cn.com.witsystem</groupId>
	<artifactId>security</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<!-- 管理依赖 -->
	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>io.spring.platform</groupId>
				<artifactId>platform-bom</artifactId>
				<version>Cairo-SR7</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>Finchley.RELEASE</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

	<repositories>
		<repository>
			<id>spring-milestones</id>
			<name>Spring Milestones</name>
			<url>https://repo.spring.io/libs-milestone</url>
			<snapshots>
				<enabled>false</enabled>
			</snapshots>
		</repository>
	</repositories>
	
	<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>
	</dependencies>
	<build>
		<plugins>
			<plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <mainClass>cn.com.witsystem.demo.DemoApplication</mainClass>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
		</plugins>
		<finalName>demo</finalName>
	</build>
</project>

yml配置文件

### 服务器端口配置  
server:
  port: 8080

应用启动类

@SpringBootApplication
@RestController
public class SecurityApplication {
	
	public static void main(String[] args) throws Exception {
		SpringApplication.run(SecurityApplication.class, args);
	}
	
	@GetMapping("/hello")
	public String hello() {
		return "hello!";
	}
}

启动测试

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.0.8.RELEASE)

2019-04-06 10:19:45.360  INFO 19624 --- [           main] c.c.w.security.SecurityApplication       : Starting SecurityApplication on DESKTOP-627VN09 with PID 19624 (D:\WitWorkSpace\security\target\classes started by ike in D:\WitWorkSpace\security)
2019-04-06 10:19:45.364  INFO 19624 --- [           main] c.c.w.security.SecurityApplication       : No active profile set, falling back to default profiles: default
2019-04-06 10:19:45.412  INFO 19624 --- [           main] ConfigServletWebServerApplicationContext : Refreshing org.springframework.boot.web.ser[email protected]6f19ac19: startup date [Sat Apr 06 10:19:45 CST 2019]; root of context hierarchy
2019-04-06 10:19:46.958  INFO 19624 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2019-04-06 10:19:46.991  INFO 19624 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2019-04-06 10:19:46.991  INFO 19624 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/8.5.37
2019-04-06 10:19:47.003  INFO 19624 --- [ost-startStop-1] o.a.catalina.core.AprLifecycleListener   : The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: [D:\Tools\java\jdk1.8_64\bin;C:\Windows\Sun\Java\bin;C:\Windows\system32;C:\Windows;D:\Tools\java\jdk1.8_64\jre\bin;D:/Tools/Java/jdk1.8_64/bin/../jre/bin/server;D:/Tools/Java/jdk1.8_64/bin/../jre/bin;D:/Tools/Java/jdk1.8_64/bin/../jre/lib/amd64;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files\NVIDIA Corporation\NVIDIA NvDLISR;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;D:\Tools\Java\jdk1.8_64\bin;D:\Nexus-3.15.2-01-win64\nexus-3.15.2-01\bin;D:\Tools\Mysql-8.0.15-winx64\bin;C:\Program Files\Git\cmd;C:\Program Files (x86)\Tesseract-OCR;C:\Users\ike\AppData\Local\Microsoft\WindowsApps;C:\Users\ike\AppData\Local\GitHubDesktop\bin;C:\Users\ike\Desktop;;.]
2019-04-06 10:19:47.108  INFO 19624 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2019-04-06 10:19:47.108  INFO 19624 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1699 ms
2019-04-06 10:19:47.204  INFO 19624 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'characterEncodingFilter' to: [/*]
2019-04-06 10:19:47.204  INFO 19624 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2019-04-06 10:19:47.205  INFO 19624 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'httpPutFormContentFilter' to: [/*]
2019-04-06 10:19:47.205  INFO 19624 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'requestContextFilter' to: [/*]
2019-04-06 10:19:47.205  INFO 19624 --- [ost-startStop-1] .s.DelegatingFilterProxyRegistrationBean : Mapping filter: 'springSecurityFilterChain' to: [/*]
2019-04-06 10:19:47.205  INFO 19624 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean  : Servlet dispatcherServlet mapped to [/]
2019-04-06 10:19:47.327  INFO 19624 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2019-04-06 10:19:47.578  INFO 19624 --- [           main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.web.ser[email protected]6f19ac19: startup date [Sat Apr 06 10:19:45 CST 2019]; root of context hierarchy
2019-04-06 10:19:47.659  INFO 19624 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/hello],methods=[GET]}" onto public java.lang.String cn.com.witsystem.security.SecurityApplication.hello()
2019-04-06 10:19:47.662  INFO 19624 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
2019-04-06 10:19:47.663  INFO 19624 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
2019-04-06 10:19:47.690  INFO 19624 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2019-04-06 10:19:47.690  INFO 19624 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2019-04-06 10:19:47.919  INFO 19624 --- [           main] .s.s.UserDetailsServiceAutoConfiguration : 

Using generated security password: 02ac1c89-ec43-4b32-b5ea-217187e973b6

2019-04-06 10:19:48.110  INFO 19624 --- [           main] o.s.s.web.DefaultSecurityFilterChain     : Creating filter chain: [email protected]1, [org.springframework.secu[email protected]697173d9, org.spring[email protected]47ac613b, [email protected]d4e, [email protected], org.[email protected]7c52fc81, org.springframework.s[email protected]28757abd, org.springframework.[email protected]18137eab, org.springfram[email protected]10a98392, org.sp[email protected]66f28a1f, org.springframework.[email protected]34d45ec0, org.springfram[email protected]ceddaf8, o[email protected]526a9908, org[email protected]c386958, org.springfr[email protected]67531e3a]
2019-04-06 10:19:48.172  INFO 19624 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2019-04-06 10:19:48.210  INFO 19624 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2019-04-06 10:19:48.216  INFO 19624 --- [           main] c.c.w.security.SecurityApplication       : Started SecurityApplication in 3.256 seconds (JVM running for 3.776)
2019-04-06 10:19:52.264  INFO 19624 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring FrameworkServlet 'dispatcherServlet'
2019-04-06 10:19:52.264  INFO 19624 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization started
2019-04-06 10:19:52.282  INFO 19624 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization completed in 18 ms

使用浏览器访问
http://localhost:8088/hello
会提示让我们登录,这是Spring Security 的默认配置。
启动的时候会在日志打印随机生成的密码,默认帐号名是user
Using generated security password: 02ac1c89-ec43-4b32-b5ea-217187e973b6
SpringBoot(2)集成Spring Security 5.0.11 入门示例
登录后结果
SpringBoot(2)集成Spring Security 5.0.11 入门示例
帐号密码我们可以通过yml配置文件配置,如果配置了帐号密码,启动日志中不会在生成密码
通过帐号密码即可登录

spring:
  security:
    user:
      name: admin
      password: password

security.basic.enable 过时问题

使用security.basic.enable=false 可以禁用Security默认认证,但是Spring Boot2.0以上版本集成Security 配置security.basic.enable已经过时了。如果我们想禁用默认的表单登录可以通过代码方式解决:

package cn.com.witsystem.security.config;

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.UserDetailsService;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.authorizeRequests().antMatchers("/**").permitAll();
	}

}

项目结构:
SpringBoot(2)集成Spring Security 5.0.11 入门示例
现在项目启动,访问不会在提示认证了。

httpBasic认证与formLogin认证

Security提供了两种默认的认证方式,formLogin是现在新版本默认的。
如果我们想使用httpBasic认证,只要修改代码:

package cn.com.witsystem.security.config;

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.UserDetailsService;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http
			.httpBasic()
			//.formLogin()
			.and()
			.authorizeRequests()
			.anyRequest()
			.authenticated();
	}

}

启动访问弹出登录对话框提示输入认证信息
SpringBoot(2)集成Spring Security 5.0.11 入门示例