Authentication:身份验证; 认证;鉴定;
Authorization:批准; 授权; 批准书; 授权书;
最常见的 principals 和 credentials 组合就是用户名/密码了。
principals 认证前是用户名,认证后是UserDetails
可以实现登陆成功和失败的接口实现更丰富的功能
AuthenticationSuccessHandler和AuthenticationFailureHandler
重写成功接口一般继承于SavedRequestAwareAuthenticationSuccessHandler。
该类的好处是可以记住你想要访问的页面,并在登录通过后自动跳转到刚才记住的你想访问的页面
重写失败接口一版继承于SimpleUrlAuthenticationFailureHandler
该类的好处是可以默认跳转到登录页
antMatchers()和regexMatchers()和mvcMatchers()
注意:antMatchers()和regexMatchers()还可以设置HttpMethod
除了配置方式,spring-security还提供了注解模式,但是默认是不开启注解配置的
需要显示指定@EnableGlobalMethodSecurity
http.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)//session的生成策略
.invalidSessionUrl("/login.html")
.sessionFixation().migrateSession()//每次都更新session,并且将旧的session属性"迁移"到新的session中
.maximumSessions(1)//限制用户的登陆个数
.maxSessionsPreventsLogin(false)//达到登陆上线后是否阻止登录
.expiredSessionStrategy(new MyExpiredSessionStrategy());//session过期策略(详见下段代码)
public class MyExpiredSessionStrategy implements SessionInformationExpiredStrategy {
private static ObjectMapper objectMapper = new ObjectMapper();
@Override
public void onExpiredSessionDetected(SessionInformationExpiredEvent event) throws IOException, ServletException {
Map<String,Object> map = new HashMap<>();
map.put("code",0);
map.put("msg","您已经在另外一台电脑或浏览器登录,被迫下线!");
event.getResponse().setContentType("application/json;charset=UTF-8");
event.getResponse().getWriter().write(
objectMapper.writeValueAsString(map)
);
}
}
角色是一种特殊的权限,ROLE_前缀
注意权限表达式的写法
@Override
protected void configure(HttpSecurity http) throws Exception {
http.addFilterBefore(captchaCodeFilter,UsernamePasswordAuthenticationFilter.class)
.logout()
.logoutUrl("/signout")
//.logoutSuccessUrl("/login.html")
.deleteCookies("JSESSIONID")
.logoutSuccessHandler(myLogoutSuccessHandler)
.and().rememberMe()
.rememberMeParameter("remember-me-new")
.rememberMeCookieName("remember-me-cookie")
.tokenValiditySeconds(2 * 24 * 60 * 60)
.tokenRepository(persistentTokenRepository())
.and().csrf().disable()
.formLogin()
.loginPage("/login.html")
.usernameParameter("uname")
.passwordParameter("pword")
.loginProcessingUrl("/login")
//.defaultSuccessUrl("/index")
//.failureUrl("/login.html")
.successHandler(mySuthenticationSuccessHandler)
.failureHandler(myAuthenticationFailureHandler)
.and().apply(smsCodeSecurityConfig).and()
.authorizeRequests()
.antMatchers("/login.html","/login",
"/kaptcha","/smscode","/smslogin").permitAll()
.antMatchers("/index").authenticated()
.anyRequest().access("@rabcService.hasPermission(request,authentication)")
.and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.invalidSessionUrl("/login.html")
.sessionFixation().migrateSession()
.maximumSessions(1)
.maxSessionsPreventsLogin(false)
.expiredSessionStrategy(new MyExpiredSessionStrategy());
}
spring-security 基于表达式的权限控制
JWT
jwt分为三部分header+payload+signature
signature的计算方式:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
跨域问题
浏览器同源策略限制
解决方案
第一类:前端解决方案
以下资源引用的标签不受同源策略的限制
- html的script标签
- html的link标签
- html的img标签
- html的iframe标签,对于使用jsp,freemarker开发的项目,这是实现跨域访问最常见的方法。
第二类:使用代理(比如nginx)
第三类:CORS(cross-origin resource sharing)
- Access-Control-Allow-Origin:允许哪些ip或域名可以跨域访问
- Access-Control-Max-Age:表示在多少秒之内不需要重复校验该请求的跨域访问权限
- Access-Control-Allow-Methods:表示允许跨域请求的HTTP方法,如:GET、POST、PUT、DELETE
- Access-Control-Allow-Headers:表示访问请求中允许携带哪些Header信息。如:Accept、Accept-Language、Content-Language、Content-Type
注意
在spring-security中推荐按照如下配置
@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("http://localhost:8888"));
configuration.setAllowedMethods(Arrays.asList("GET","POST"));
configuration.applyPermitDefaultValues();
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
CORS和CSRF
CORS(cross-origin resource sharing)跨域资源共享
CSRF(cross-site request forgery)跨站请求伪造
CSRF是不防GET请求的