Spring Security 表单配置(一)
- 工具版本及环境
- 参考资源
- 配置详细
- 说明
工具版本及环境
工具:
IDEA 2021.3
Maven 3.8.6
JDK 8
Spring Boot 2.7.7
Spring Securiity 5.7.6
参考资源
Spring Security官网: https://docs.spring.io/spring-security/reference/5.7/index.html
这里参考的是Servlet文档,英文文档看不懂可以借助Edge浏览器翻译一下,虽然满屏春豆的翻译看起来不怎么地道,但是连蒙带猜还是能理解点东西的,而且里面的图片看着也很清楚明白。
官网github的示例程序:https://github.com/spring-projects/spring-security
gitee我fork了一份:https://gitee.com/qkzztx_admin/spring-security-samples
配置详细
废话不多说,先上码。
gitee完整例子:https://gitee.com/qkzztx_admin/security-demo 检出tag v1
package security.demo.config;
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.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.formLogin(form -> {
form
.loginProcessingUrl("/login") // 接受登录请求的url,默认也是login
.loginPage("/toLogin") // 表单对应的url
.successForwardUrl("/success") // 登录成功后重定向的url
.failureForwardUrl("/failure") // 登录失败后重定向的url
;
})
.authorizeHttpRequests().anyRequest().authenticated() // 授权任何一个请求都必须认证才能访问
.and()
.csrf().disable(); // 简单粗暴禁用csrf
return http.build();
}
@Bean
public UserDetailsService userDetailsService() {
return new MyUserDetailsService();
}
// 密码加密类
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
package security.demo.config;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
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.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class MyUserDetailsService implements UserDetailsService {
// 临时的用户信息
public static final Map<String, UserDetails> userStore = new HashMap<>();
@Resource
private PasswordEncoder passwordEncoder;
@PostConstruct
public void init() {
String username = "admin";
String password = "admin";
userStore.put(username, createUser(username, password, Collections.singletonList("admin")));
String username1 = "user";
String password1 = "user";
userStore.put(username1, createUser(username1, password1, Arrays.asList("user", "roleA")));
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
UserDetails userDetails = userStore.get(username);
// 这里创建一个新的,否则登录成功后,密码会被设置为null,导致后续认证失败
// 如果从数据库读取没有这种问题
return new User(userDetails.getUsername(),
userDetails.getPassword(),
userDetails.getAuthorities());
}
private User createUser(String username, String password, List<String> authority) {
Set<GrantedAuthority> authorities = new HashSet<>();
for (String permission : authority) {
authorities.add(new SimpleGrantedAuthority(permission));
}
return new User(username,passwordEncoder.encode(password), authorities);
}
}
package security.demo.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class LoginController {
@RequestMapping("/toLogin")
public String toLogin() {
return "toLogin";
}
@RequestMapping("/success")
public String loginSuccess() {
return "loginSuccess";
}
@RequestMapping("/failure")
public String loginFailure() {
return "loginFailure";
}
}
说明
- 如果使用form表单登录的话,自定义拦截/login是没用的,只能实现固定的接口实现自定义登录。
- 也可以使用默认的form表单配置,不用自定义各种url,使用spring security默认的表单模板
- spring security支持的配置太多太全,这里只是一点点配置
- csrf跨站请求伪造过滤器不利于调试,这里直接粗暴的禁用了,应该还有其他优雅的姿势。