springSecurity

文档

https://docs.spring.io/spring-security/site/docs/5.2.2.RELEASE/reference/htmlsingle/#csrf-explained

HTTPBASIC模式

最简单的提示框输入密码模式,实际上密码和账号只是存在请求头中的Authorization字段中,用Base64加密,十分容易被破解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Override
protected void configure(HttpSecurity http) throws Exception {

http.httpBasic()
.and()
.authorizeRequests().anyRequest()
.authenticated();

}

}

formLogin模式

适用于表单提交的方式登录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Override
protected void configure(HttpSecurity http) throws Exception {

http.csrf().disable()
.formLogin()
.loginPage("/login.html")
.usernameParameter("uname")
.passwordParameter("pword")
.loginProcessingUrl("/login")
.defaultSuccessUrl("/index")
.and()
.authorizeRequests()
.antMatchers("/login.html","/login").permitAll()
.antMatchers("/biz1","/biz2") //需要对外暴露的资源路径
.hasAnyAuthority("ROLE_user","ROLE_admin") //user角色和admin角色都可以访问
//.antMatchers("/syslog","/sysuser")
//.hasAnyRole("admin") //admin角色可以访问
//.hasAnyAuthority("ROLE_admin")
.antMatchers("/syslog").hasAuthority("sys:log")
.antMatchers("/sysuser").hasAuthority("sys:user")
.anyRequest().authenticated();

}


@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user")
.password(passwordEncoder().encode("123456"))
.roles("user")
.and()
.withUser("admin")
.password(passwordEncoder().encode("123456"))
.authorities("sys:log","sys:user")
//.roles("admin")
.and()
.passwordEncoder(passwordEncoder());//配置BCrypt加密
}

@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}

@Override
public void configure(WebSecurity web) {
//将项目中静态资源路径开放出来
web.ignoring()
.antMatchers( "/css/**", "/fonts/**", "/img/**", "/js/**");
}

}

Session的创建与使用

  • always:如果当前请求没有session存在,SpringSecurity创建一个session
  • never:SpringSercurity将永远不会创建一个Session,但是如果Session已经存在,它将使用Session
  • ifRquired(默认):SpringSecurity在需要时才创建session
  • stateless:SpringSecurity不会创建或使用任何Session,适合接口型无状态的应用,该方式节省资源
1
httpSecurity.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)

Session的保护

默认情况下SpringSecurity启用了migratonSession的保护方式,即对同一个cookies的SESSIONID用户,每次登陆验证将创建一个新的HTTP会话,旧的HTTP会话将无效,并且旧会话的属性会被复制。设置为“none”的时候,原始会话不会无效,设置“newSession”后,将创建一个干净的会话,而不会复制会话中的任何属性。

1
httpSecurity.sessionManagement().sessionFixation().migrateSession();

Cookie的安全

  • httponly:如果为true,则通过浏览器脚本无法访问cookie
  • secure:如果为true,则仅通过HTTPS发送cookie,HTTP无法接待cookie
1
2
server.servlet.session.cookie.http-only=true;
server.servlet.session.cookie.secure=true;

从数据库动态加载角色信息

  • 实现UserDetailsService接口实现loadUserByUsername方法
  • 实现UserDetails接口,实现所有方法

从数据动态加载权限规则信息

1
http.authorizeRequests()            .anyRequest().access("@rabcService.hasPermission(request,authentication)")

权限表达式

ExpressionDescription

hasRole(String role)

Returns true if the current principal has the specified role.

For example, hasRole(‘admin’)

By default if the supplied role does not start with ‘ROLE_’ it will be added.
This can be customized by modifying the defaultRolePrefix on DefaultWebSecurityExpressionHandler.

hasAnyRole(String… roles)

Returns true if the current principal has any of the supplied roles (given as a comma-separated list of strings).

For example, hasAnyRole(‘admin’, ‘user’)

By default if the supplied role does not start with ‘ROLE_’ it will be added.
This can be customized by modifying the defaultRolePrefix on DefaultWebSecurityExpressionHandler.

hasAuthority(String authority)

Returns true if the current principal has the specified authority.

For example, hasAuthority(‘read’)

hasAnyAuthority(String… authorities)

Returns true if the current principal has any of the supplied authorities (given as a comma-separated list of strings)

For example, hasAnyAuthority(‘read’, ‘write’)

principal

Allows direct access to the principal object representing the current user

authentication

Allows direct access to the current Authentication object obtained from the SecurityContext

permitAll

Always evaluates to true

denyAll

Always evaluates to false

isAnonymous()

Returns true if the current principal is an anonymous user

isRememberMe()

Returns true if the current principal is a remember-me user

isAuthenticated()

Returns true if the user is not anonymous

isFullyAuthenticated()

Returns true if the user is not an anonymous or a remember-me user

hasPermission(Object target, Object permission)

Returns true if the user has access to the provided target for the given permission.
For example, hasPermission(domainObject, ‘read’)

hasPermission(Object targetId, String targetType, Object permission)

Returns true if the user has access to the provided target for the given permission.
For example, hasPermission(1, ‘com.example.domain.Message’, ‘read’)

方法级别的权限控制

1
2
@EnableGlobalMethodSecurity(prePostEnabled = true)
@PreAuthorize, @PreFilter, @PostAuthorize @PostFilter

Remember记住密码

CSRF