Spring Security是一个基于Spring框架的安全性框架。
它提供了诸如认证、授权、攻击防御等功能,可以保护Web应用程序中的资源。
验证用户的身份。
限制用户对应用程序的访问。
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-securityartifactId>
dependency>
引入后项目就能使用了。
未登录用户会自动跳转到Spring Security提供的登录页面。
登录不可能使用Spring Security默认配置,我们需要用自己的账户去登录。
如果我们需要进行以下配置。
@Service
public class MyUserDetailsService implements UserDetailsService {
public static record MyUser(String username,String password){};
public MyUser queryUserFromDB(String username){
//todo 自定义从数据库查询用户数据
//这里我定死了一个用户
return new MyUser(username,"123456");
}
// 自定义认证逻辑
@Override
public UserDetails loadUserByUsername(String username){
// 1.查询用户
MyUser user = queryUserFromDB(username);
// 2.封装为UserDetails对象
UserDetails userDetails = User
.withUsername(user.username)
.password(user.password)
.authorities("admin")
.build();
// 3.返回封装好的UserDetails对象
return userDetails;
}
/**
* 配置密码解析器
* 假如数据库密码没加密,使用NoOpPasswordEncoder
* 假如数据库密码有加密,使用NBCryptPasswordEncoder
* @return
*/
@Bean
public PasswordEncoder passwordEncoder(){
return NoOpPasswordEncoder.getInstance();
}
}
Spring Security提供了登录页面,但我们更多的是使用自己的登录页面。
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter{
//Spring Security配置
@Override
protected void configure(HttpSecurity http) throws Exception {
// 自定义表单登录
http.formLogin()
.loginPage("/login.html") //自定义登录页面
.usernameParameter("username")// 表单中的用户名项
.passwordParameter("password")// 表单中的密码项
.loginProcessingUrl("/login") // 登录路径,表单向该路径提交,提交后自动执行UserDetailsService的方法
.successForwardUrl("/index")//登录成功后跳转的路径
.failureForwardUrl("/fail");//登录失败后跳转的路径
// 配置需要认证的资源
http.authorizeRequests()
.antMatchers("/login.html").permitAll() //登录页不需要认证
.anyRequest().authenticated();//其余所有请求都需要认证
//关闭csrf防护,默认开启了CSRF防护
http.csrf().disable();
}
@Override
public void configure(WebSecurity web) throws Exception {
// 静态资源放行
web.ignoring().antMatchers("/css/**");
web.ignoring().antMatchers("/js/**");
web.ignoring().antMatchers("/img/**");
}
}
public class MyLoginSuccessHandler implements AuthenticationSuccessHandler {
@Override
public void onAuthenticationSuccess(HttpServletRequest
request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
// 拿到登录用户的信息
UserDetails userDetails = (UserDetails)authentication.getPrincipal();
//todo 自定义登录成功操作
// 重定向到主页
response.sendRedirect("/index");
}
}
在SecurityConfig 配置 AuthenticationSuccessHandler
public class SecurityConfig extends WebSecurityConfigurerAdapter{
//Spring Security配置
@Override
protected void configure(HttpSecurity http) throws Exception {
//http.successForwardUrl("/index")
http.successHandler(new MyLoginSuccessHandler()) //登录成功处理器
//定义successHandler后就不用设置successForwardUrl
}
}
public class MyLoginFailureHandler implements AuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) throws IOException, ServletException {
//todo 自定义失败操作
response.sendRedirect("/fail");
}
}
在SecurityConfig 配置 AuthenticationFailureHandler
public class SecurityConfig extends WebSecurityConfigurerAdapter{
//Spring Security配置
@Override
protected void configure(HttpSecurity http) throws Exception {
//http.failureForwardUrl("/fail");
http.failureHandler(new MyLoginFailureHandler());
//定义failureHandler后就不用设置failureForwardUrl
}
}
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter{
//Spring Security配置
@Override
protected void configure(HttpSecurity http) throws Exception {
// 退出登录配置
http.logout()
.logoutUrl("/logout") // 退出登录路径
.logoutSuccessUrl("/login.html") // 退出登录后跳转的路径
.clearAuthentication(true) //清除认证状态,默认为true
.invalidateHttpSession(true); // 销毁HttpSession对象,默认为true
}
}
@RestController
public class MyController {
// 获取当前登录用户名
@RequestMapping("/users/username")
public String getUsername(){
// 1.获取会话对象
SecurityContext context = SecurityContextHolder.getContext();
// 2.获取认证对象
Authentication authentication = context.getAuthentication();
// 3.获取登录用户信息
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
return userDetails.getUsername();
}
}
原文 : https://developer.aliyun.com/article/1135702