添加Security依赖项在pom.xml中
<!-- Spring Boot中的Spring Security的依赖项,用于处理认证与授权 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
SecurityConfiguration
- 通常情况下,我们会通过重写configure(AuthenticationManagerBuilder auth)方法来配置身份验证,添加自定义的用户认证逻辑。因为源码中
this.disableLocalConfigureAuthenticationBldr = true;
这一行代码的作用是禁用本地的身份验证配置。
package cn.tedu.tea.admin.server.core.config;
import cn.tedu.tea.admin.server.common.web.JsonResult;
import cn.tedu.tea.admin.server.common.web.ServiceCode;
import cn.tedu.tea.admin.server.core.filter.JwtAuthorizationFilter;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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.config.http.SessionCreationPolicy;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* Spring Security的配置类
*
* @author java@tedu.cn
* @version 1.0
*/
@Slf4j
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true) // 开启基于方法的安全检查
// @EnableWebSecurity(debug = true) // 开启调试模式,在控制台将显示很多日志,在生产环境中不宜开启
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {//继承WebSecurityConfigurerAdapter类才算是Security配置类
@Autowired
private JwtAuthorizationFilter jwtAuthorizationFilter;
public SecurityConfiguration() {
log.debug("创建配置类对象:SecurityConfiguration");
}
@Bean
public PasswordEncoder passwordEncoder() {
// return NoOpPasswordEncoder.getInstance();
return new BCryptPasswordEncoder();
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// 配置Security框架不使用Session
// SessionCreationPolicy.NEVER:从不主动创建Session,但是,Session存在的话,会自动使用
// SessionCreationPolicy.STATELESS:无状态,无论是否存在Session,都不使用
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
// 将自定义的解析JWT的过滤器添加到Security框架的过滤器链中
// 必须添加在检查SecurityContext的Authentication之前,具体位置并不严格要求
http.addFilterBefore(jwtAuthorizationFilter, UsernamePasswordAuthenticationFilter.class);
// 允许跨域访问,本质上是启用了Security框架自带的CorsFilter
http.cors();
// 处理“无认证信息却访问需要认证的资源时”的响应
http.exceptionHandling().authenticationEntryPoint(new AuthenticationEntryPoint() {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException {
log.warn("{}", e);
response.setContentType("application/json; charset=utf-8");
String message = "操作失败,您当前未登录!";
JsonResult jsonResult = JsonResult.fail(ServiceCode.ERROR_UNAUTHORIZED, message);
PrintWriter writer = response.getWriter();
writer.println(JSON.toJSONString(jsonResult));
writer.close();
}
});
// 白名单
String[] urls = {
"/favicon.ico",//浏览器某个图标
"/doc.html",
"/**/*.css",
"/**/*.js",
"/swagger-resources",//需要加上,要不然是白板
"/v2/api-docs",//需要加上,要不然是白板
"/resources/**", // 静态资源文件夹,通常是上传的文件,请与配置文件中的"tea-store.upload.base-dir-name"一致
"/account/users/login" // 用户登录
};
// 禁用“防止伪造的跨域攻击的防御机制”
http.csrf().disable();
// 配置请求授权
// 如果某个请求被多次配置,按照“第一匹配原则”处理
// 应该将精确的配置写在前面,将较模糊的配置写在后面
http.authorizeRequests()//获取一个用于配置请求授权的对象
.mvcMatchers(urls) // 匹配某些请求
.permitAll() // 许可,即不需要通过认证就可以访问
.anyRequest() // 任何请求,从执行效果来看,也可以视为:除了以上配置过的以外的其它请求
.authenticated(); // 需要通过认证才可以访问
// 是否调用以下方法,将决定是否启用默认的登录页面
// 当未通过认证时,如果有登录页,则自动跳转到登录,如果没有登录页,则直接响应403
// http.formLogin();
// super.configure(http); // 不要调用父类的同名方法,许多默认的效果都是父类方法配置的
}
}
http.csrf().disable();这行代码的作用
这段代码是在使用Spring Security配置CSRF(跨站请求伪造)保护时的一个配置方法。具体来说,http.csrf().disable()
方法用于禁用CSRF保护。
CSRF是一种常见的Web攻击,攻击者通过利用用户在访问恶意网站时的身份验证信息,发送伪造的请求来执行非法操作。为了防止CSRF攻击,Spring Security默认启用CSRF保护。
调用http.csrf().disable()
方法可以禁用CSRF保护机制。这意味着在配置中关闭CSRF保护后,应用程序将不会验证请求是否包含有效的CSRF令牌。禁用CSRF保护可能会有一定的风险,因此在禁用之前应该仔细评估应用程序的安全需求。
禁用CSRF保护通常用于以下情况之一:
- 应用程序不使用表单提交,或者不以表单方式进行操作;
- 应用程序已经通过其他方式(如使用令牌)保护了对敏感操作的访问。
需要注意的是,在禁用CSRF保护时,我们需要确保应用程序有其他有效的安全措施来防止CSRF攻击。例如,可以使用双重身份验证、验证码、限制敏感操作的访问权限等。