protected void configure(HttpSecurity http) throws Exception {
//自动登录的令牌持久化到
JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
jdbcTokenRepository.setDataSource(dataSource);
http.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/user/**").hasRole("USER")
.antMatchers("/API/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
//自定义登录页
/*.loginPage("/myLogin.html")
.loginProcessingUrl("/login")
.permitAll() */
.and()
.rememberMe()
.and()
// 配置 配置防御回话固定攻击策略
.sessionManagement().sessionFixation().newSession()
.and()
.csrf().disable();
}
1、配置session过期跳转某个路由
// 配置 配置防御回话固定攻击策略
.sessionManagement().sessionFixation().newSession()
// 配置session过期跳转的路由
.invalidSessionUrl("/session/invalid")
2、自定义session过期策略
public class MyInvalidSessionStrategy implements InvalidSessionStrategy{
@Override
public void onInvalidSessionDetected(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
ResponseData res = new ResponseData<>(500, "sesson过期");
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
response.getWriter().write(JSON.toJSONString(res));
}
}
.and()
// 配置 配置防御回话固定攻击策略
.sessionManagement().sessionFixation().newSession()
// 配置session过期跳转的路由
// .invalidSessionUrl("/session/invalid")
// 配置session过期的处理策略
.invalidSessionStrategy(new MyInvalidSessionStrategy())
设置session的并发数为1
当在一个session会话中登陆后,在另一个session会话中进行登录时,第一个sessiong会话会过期
.sessionManagement().sessionFixation().newSession()
// 配置session过期跳转的路由
// .invalidSessionUrl("/session/invalid")
// 配置session过期的处理策略
.invalidSessionStrategy(new MyInvalidSessionStrategy())
// 配置session的并发数为1
.maximumSessions(1)
当在一个session会话中登陆后,在另一个session会话中进行登录时,登陆操作会被阻止
// 配置 配置防御回话固定攻击策略
.sessionManagement().sessionFixation().newSession()
// 配置session过期跳转的路由
// .invalidSessionUrl("/session/invalid")
// 配置session过期的处理策略
.invalidSessionStrategy(new MyInvalidSessionStrategy())
// 配置session的并发数为1
.maximumSessions(1)
.maxSessionsPreventsLogin(true);
1)将BCryptPasswordEncoder 注入到容器中
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
2)WebSecurityConfig 中配置密码加密方式
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(myUserDetailsService)
.passwordEncoder(passwordEncoder);
}
1)校验密码时,对数据库中存储的密码进行区分,如果不是BCrypt形式的,则使用以前老的校验密码的方式
2)不仅想要兼容,还想将不安全的旧密码无缝修改成BCrypt密文,该如何操作
有两种方式解决以上情况
很多人误认为资源跨域时无法请求,实际上,通常情况下请求是可以正常发起的(注意,部分浏 览器存在特例),后端也正常进行了处理,只是在返回时被浏览器拦截,导致响应内容不可使用
浏览器解决跨域问题的方法有多种,包括JSONP、Nginx转发和CORS等。其中,JSONP和CORS需 要后端参与。
CORS(Cross-Origin Resource Sharing)的规范中有一组新增的HTTP首部字段,允许服务器声明其 提供的资源允许哪些站点跨域使用。通常情况下,跨域请求即便在不被支持的情况下,服务器也会接 收并进行处理,在CORS的规范中则避免了这个问题。浏览器首先会发起一个请求方法为OPTIONS 的预检请求,用于确认服务器是否允许跨域,只有在得到许可后才会发出实际请求
CORS新增的HTTP首部字段由服务器控制,下面我们来看看常用的几个首部字段:
简单请求、预检请求、带凭证的请求
简单请求
在CORS中,并非所有的跨域访问都会触发预检请求。例如,不携带自定义请求头信息的GET 请 求、HEAD 请求,以及 Content-Type 为application/x-www-form-urlencoded、multipart/form-data或text/plain的POST请求,这类请求被称为简单请求。
预检请求
text/plain的POST请求,这类请求被称为简单请求。
预检请求不同于简单请求,它会发送一个 OPTIONS 请求到目标站点,以查明该请求是否安全, 防止请求对目标站点的数据造成破坏。若是请求以 GET、HEAD、POST 以外的方法发起;或者使用 POST方法,但请求数据为application/x-www-form-urlencoded、multipart/form-data和text/plain以外的数据类型;再或者,使用了自定义请求头,则都会被当成预检请求类型处理
带凭证的请求
简单来说就是请求携带了cookie等信息
1)如何启用 SpringSecurity对cros的支持
只需在配置器中启用CORS支持,并编写一 个CORS配置源即可
@Bean
public CorsConfigurationSource corsConfigurationSource() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration corsConfiguration = new CorsConfiguration();
//1、配置跨域
corsConfiguration.addAllowedHeader("*");
corsConfiguration.addAllowedMethod("*");
corsConfiguration.addAllowedOrigin("*");
corsConfiguration.setAllowCredentials(true);
source.registerCorsConfiguration("/**",corsConfiguration);
return source;
}
2)原理
DefaultCorsProcessor中的handleInternal方法
CSRF的全称是(Cross Site Request Forgery)
1、HTTP Referer
HTTP Referer是由浏览器添加的一个请求头字段,用于标识请求来源。
2、CsrfToken认证
CSRF是利用用户的登录态进行攻击的,而用户的登录态记录在cookie中。其实攻击者并不知道用 户的cookie存放了哪些数据,于是想方设法让用户自身发起请求,这样浏览器便会自行将cookie传送到服务器完成身份校验