Spring Security 一个小 Demo
参考教程
主要参考了 Spring Security最简单全面教程(带Demo)
问题解决
遇到了 javax.servlet.ServletException: Circular view path
的问题,访问 http://localhost:8080/login 时一直 404。
Thymeleaf 依赖
看到 HTML 文件里面有用到 th:if=
的语法,参考 SpringBoot整合Thymeleaf快速入门(附详细教程) 添加了依赖
视图解析
还是访问不了,发现模板是默认放到 templates 文件夹下的,但是移动后还是访问不了。参考 springboot视图解析器配置(yml版配置) 配置了视图解析,就可以了。
最终结果
实践效果
访问 http://localhost:8080/home 时不用验证。
访问 http://localhost:8080/hello 会自动跳转到 login 页。
只有 admin 用户可以访问 http://localhost:8080/admin 页。
代码地址
项目地址。
核心代码
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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>fun.seolas</groupId>
<artifactId>spring-security-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.2.RELEASE</version>
</parent>
<dependencies>
<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-thymeleaf</artifactId>
</dependency>
</dependencies>
</project>
application.yaml
#yml配置
spring:
mvc:
# 视图解析器
view:
prefix: /imf/
suffix: .html
# 静态资源访问前缀(区分动态资源和静态资源)
static-path-pattern: /imf/**
# 静态资源的加载路径
resources:
static-locations: classpath:/templates/
SecurityConfig.java
package fun.seolas.config;
import org.springframework.context.annotation.Configuration;
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;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@Configuration
@EnableWebSecurity //启用Web安全功能
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
//访问"/"和"/home"路径的请求都允许
.antMatchers("/", "/home", "/staff", "/staff/*")
.permitAll()
//而其他的请求都需要认证
.anyRequest()
.authenticated()
.and()
//修改Spring Security默认的登陆界面
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//基于内存来存储用户信息
auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
.withUser("user").password(new BCryptPasswordEncoder().encode("123")).roles("USER").and()
.withUser("admin").password(new BCryptPasswordEncoder().encode("456")).roles("USER", "ADMIN");
}
}
MethodSecurityConfig.java
package fun.seolas.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration;
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true,jsr250Enabled = true,prePostEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
}
SecurityController.java
package fun.seolas.controller;
import org.springframework.security.access.annotation.Secured;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class SecurityController {
@GetMapping(value = {"/home","/"})
public String home(){
return "home";
}
@GetMapping(value = "/hello")
public String hello(){
return "hello";
}
@GetMapping(value = "/login")
public String login(){
return "login";
}
@GetMapping(value = "/admin")
@Secured("ROLE_ADMIN")
public String admin(){
return "admin";
}
}