package cn.tedu.csmall.product.config;
import cn.tedu.csmall.product.filter.JwtAuthorizationFilter;
import cn.tedu.csmall.commons.web.JsonResult;
import cn.tedu.csmall.commons.web.ServiceCode;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
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.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.AuthenticationException;
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;
@Slf4j
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true) // 开启全局的基于方法的安全检查, 即: 在方法上添加注解来检查权限
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private JwtAuthorizationFilter jwtAuthorizationFilter;
@Override
protected void configure(HttpSecurity http) throws Exception {
// 开启Spring Security自带的CorsFilter, 已解决跨域问题
//对于复杂请求,浏览器会先对服务器端发送OPTIONS类型的请求,以执行预检(PreFlight),如果预检通过,才会执行本应该发送的请求。
http.cors();
// 配置Spring Security框架使用(创建) Session的策略
// (确保不携带JWT, SpringSecurity不能基于Session找到SecurityContext并读取到认证信息)
// STATELESS: 无状态的, 完全不使用Session
// NEVER: 从不主动创建session, 但是,当Session已经被创建后, 仍会正常使用
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
// 将JWT过滤器添加到Spring Security框架的某些过滤器之前
// 能在路过滤器前执行的只有过滤器
http.addFilterBefore(jwtAuthorizationFilter, UsernamePasswordAuthenticationFilter.class);
//处理未通过认证时访问受保护的资源时被拒绝访问
http.exceptionHandling().authenticationEntryPoint(new AuthenticationEntryPoint() {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException e) throws IOException, ServletException {
String message = "您当前未登录, 请先登录!";
log.warn(message);
JsonResult jsonResult = JsonResult.fail(ServiceCode.ERR_UNAUTHORIZED, message);
String jsonString = JSON.toJSONString(jsonResult);
response.setContentType("application/json;charset=utf-8");
PrintWriter printWriter = response.getWriter();
printWriter.println(jsonString);
printWriter.close();
}
});
// 禁用"防止伪造的跨域攻击的防御机制"
http.csrf().disable();
// 白名单
/*
使用1个星号,可以通配此层级的任何资源,
例如:/admin/*,可以匹配:/admin/add-new、/admin/list,但不可以匹配:/admin/password/change
使用2个连续的星可以,可以通配若干层级的资源,
例如:/admin/**,可以匹配:/admin/add-new、/admin/password/change
*/
String[] urls = {
"/doc.html",
"/**/*.css",
"/**/*.js",
"/swagger-resources",
"/v2/api-docs"
};
// 配置授权访问
// 注意:以下授权访问的配置,是遵循“第一匹配原则”的,即“以最先匹配到的规则为准”
// 例如:anyRequest()是匹配任何请求,通常,应该配置在最后,表示“除了以上配置过的以外的所有请求”
// 所以,在开发实践中,应该将更具体的请求配置在靠前的位置,将更笼统的请求配置在靠后的位置
http.authorizeRequests() // 开始对请求进行授权
/*.mvcMatchers(HttpMethod.OPTIONS,"/**")
.permitAll()
// 以上两句将所有OPTIONS类型的请求全部直接许可*/
.mvcMatchers(urls) // 匹配某些请求
.permitAll() // 许可, 即不需要通过认证就可以访问
.anyRequest() // 任何请求, 通常在最后配置
.authenticated(); // 要求已经完成认真的
// 如果调用以下方法, 当Security认为需要通过认证, 但实际未通过认证时, 就会跳转到登录页面
// 如果为调用以下方法, 将会响应403错误
// http.formLogin();
// Spring Security框架的典型特征 都是默认调用了父类的方法
// super.configure(http); 不要保留调用父级同名方法的代码
}
}
Spring Security 配置类
最新推荐文章于 2024-08-29 17:16:23 发布