一、介绍
Spring Security是一个基于Spring框架的安全性框架。
它提供了诸如认证、授权、攻击防御等功能,可以保护Web应用程序中的资源。
二、作用
认证(Authentication)
验证用户的身份。
授权(Authorization)
限制用户对应用程序的访问。
三、SpringBoot项目使用
1、maven依赖
<!--Spring Security-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId>
</dependency>
引入后项目就能使用了。
未登录用户会自动跳转到Spring Security提供的登录页面。
- 默认用户:user;
- 默认密码:会在控制台打印Using generated security password: xxxxx 。
2、认证配置——实现 UserDetailsService 接口
登录不可能使用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");}// 自定义认证逻辑@Overridepublic 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*/@Beanpublic PasswordEncoder passwordEncoder(){return NoOpPasswordEncoder.getInstance();}
}
3、登录页面配置——继承 WebSecurityConfigurerAdapter 类
Spring Security提供了登录页面,但我们更多的是使用自己的登录页面。
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter{//Spring Security配置@Overrideprotected 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();}@Overridepublic void configure(WebSecurity web) throws Exception {// 静态资源放行web.ignoring().antMatchers("/css/**");web.ignoring().antMatchers("/js/**");web.ignoring().antMatchers("/img/**");}
}
4、如果登录成功/失败,需要额外处理。
登录成功——实现AuthenticationSuccessHandler 接口
public class MyLoginSuccessHandler implements AuthenticationSuccessHandler {@Overridepublic 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配置@Overrideprotected void configure(HttpSecurity http) throws Exception {//http.successForwardUrl("/index")http.successHandler(new MyLoginSuccessHandler()) //登录成功处理器//定义successHandler后就不用设置successForwardUrl}
}
登录失败——实现AuthenticationFailureHandler 接口
public class MyLoginFailureHandler implements AuthenticationFailureHandler {@Overridepublic void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) throws IOException, ServletException {//todo 自定义失败操作response.sendRedirect("/fail");}
}
在SecurityConfig 配置 AuthenticationFailureHandler
public class SecurityConfig extends WebSecurityConfigurerAdapter{//Spring Security配置@Overrideprotected void configure(HttpSecurity http) throws Exception {//http.failureForwardUrl("/fail");http.failureHandler(new MyLoginFailureHandler());//定义failureHandler后就不用设置failureForwardUrl}
}
5、退出配置
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter{//Spring Security配置@Overrideprotected void configure(HttpSecurity http) throws Exception {// 退出登录配置http.logout().logoutUrl("/logout") // 退出登录路径.logoutSuccessUrl("/login.html") // 退出登录后跳转的路径.clearAuthentication(true) //清除认证状态,默认为true.invalidateHttpSession(true); // 销毁HttpSession对象,默认为true}
}
6、Controller获取登录用户信息
@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