旧日版回顾:1.0版本
门的本质就是阻挡前往目的地的问题,再简单点门 === 问题
也就是说,只要这个东西拦住你前往目的,那他就可以赋予一个名——门!!!
第一道验证:立门 -》authorizeHttpRequests 第二道验证:非法越门警告 -》exceptionHandling 第三道验证:数据库用户信息 -》userDetailsService 第四道验证:登录验证 -》formLogin 第五道验证:退出验证 -》logout 第六道验证:记住登录 -》rememberMe 第七道验证:异地防御,远程登录 -》cors(跨源资源共享) 第八道验证:金库保险门 -》CSRF(在未上线时,为了方便自己建议关闭,上线了记得开启!!!) 构建特殊的门!!!
这是目前所用到的八道门!,配置采用lambda表达式
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception{
return http
.authorizeHttpRequests(cof ->{
cof.requestMatchers("/api/auth/**").permitAll();//大门可放行区
cof.anyRequest().authenticated();//任何请求都要通过大门
})
.exceptionHandling(cof ->{
cof.authenticationEntryPoint(this::onAuthenticationFailure);//暴力非法闯入警告
})
.userDetailsService(userService)
.formLogin(cof ->{
cof.loginProcessingUrl("/api/auth/login");//登录验证门的位置
cof.successHandler(this::onAuthenticationSuccess);//成功登录提示
cof.failureHandler(this::onAuthenticationFailure);//登录失败提示
})
.logout(cof ->{
cof.logoutUrl("/api/auth/logout");//退出登录门的位置
cof.logoutSuccessHandler(this::onAuthenticationSuccess);//成功退出提示
})
.rememberMe(cof->{
cof.rememberMeParameter("remember");//记住登录关键词
cof.tokenRepository(tokenRepository());//凭证存储器
cof.tokenValiditySeconds(3600 * 24 *7);//过期时间
})
.cors(cof ->{
cof.configurationSource(configurationSource());//自定义cors
})
.csrf(AbstractHttpConfigurer::disable)//关闭金库大门
.build();
}
@Bean
public BCryptPasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();//加密
}
//储存登录token于数据库
@Bean
public PersistentTokenRepository tokenRepository(){
JdbcTokenRepositoryImpl repository = new JdbcTokenRepositoryImpl();
repository.setDataSource(dataSource);//数据源
repository.setCreateTableOnStartup(false);//每次启动时自动创建数据库表单储存token(),在第一次启动时,使用true创建表单,后续使用false
return repository;
}
//自定义cors配置
private CorsConfigurationSource configurationSource(){
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedOriginPattern("*");
corsConfiguration.setAllowCredentials(true);
corsConfiguration.addAllowedHeader("*");
corsConfiguration.addAllowedMethod("*");
corsConfiguration.addExposedHeader("*");
UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
urlBasedCorsConfigurationSource.registerCorsConfiguration("/**",corsConfiguration);
return urlBasedCorsConfigurationSource;
}
//成功响应头
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
response.setHeader("Content-Type", "text/plain; charset=UTF-8");//中文响应
response.setCharacterEncoding("UTF-8");
//请求路径如果是login,响应登陆成功
if (request.getRequestURI().endsWith("/login")){
response.getWriter().write(JSONObject.toJSONString(Result.success("登录成功")));//转换成json
}
//请求路径如果是logout,响应登录失败
if (request.getRequestURI().endsWith("/logout")){
response.getWriter().write(JSONObject.toJSONString(Result.success("退出登录成功")));//转换成json
}
}
//失败响应头
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
response.setHeader("Content-Type", "text/plain; charset=UTF-8");//中文响应
response.setCharacterEncoding("UTF-8");
response.getWriter().write(JSONObject.toJSONString(Result.error(exception.getMessage())));//转换成json
}
响应内容模板:
@Data
//json格式实体类
public class Result<T> {
private Integer code;
private boolean success;
private T message;
public Result(Integer code, boolean success, T message) {
this.code = code;
this.success = success;
this.message = message;
}
public static <T> Result<T> success(){
return new Result<>(0,true,null);
}
public static <T> Result<T> success(T data){
return new Result<>(0,true,data);
}
public static <T> Result<T> error(T message){
return new Result<>(1,false,message);
}
}