安全控制Spring Security
1. Spring Security
Spring Security 是专门针对基于spring的项目的安全框架,充分利用了依赖注入和AOP来实现安全的功能。
安全框架有两个重要概念,即认证(Authentication)和授权(Authorization)。认证即确认用户可以访问当前系统;授权即确定用户在当前系统下所有的功能权限。
Spring Security为我们提供了一个多个过滤器来实现所有安全的功能,我们只需要注册一个特殊的DelegatingFilterProxy过滤器到WebApplicationInitalizer(抽象类:AbstractSecirotuWebApplicationInitalizer)即可。
2.依赖:
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
</dependency>
开启过滤支持:
public class MyInitializer extends AbstractSecirotuWebApplicationInitalizer
{
}
3. 配置:
@Configuration
@EnableWebSecurity
public class WebSecurtiyConfig extends WebSecurityConfigurerAdapter{
@Autowired
DataSource dataSource;
@Bean
UserDetailsService customUserService(){
return new CustomUserService();
}
/**用户认证*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception{
/**1.内存中的用户*/
auth.inMemoryAuthentication()
.withUser("shm").password("123456").roles("ROLE_ADMIN")
.and()
.withUser("xxy").password("123456").roles("ROLE_ADMIN");
/**2.JDBC中的用户*/
auth.jdbcAuthentication().dataSource(dataSource)
.usersByUsernameQuery("select username,password,true from myusers where username=?")
.authoritiesByUsernameQuery()"select username,role from myusers where username=?";
/**3.通用的用户*/
auth.useDetailsService(customUserService());
}
@Override
protected void configure(HttpSecurity http) throws Exception{
/**4.请求授权
*Spring Security使用以下匹配器来匹配路径
*antMatchers: 使用Ant风格的路径匹配
*regexMatchers: 使用正则表达式匹配路径
*anyRequest: 匹配所有请求路径
*/
http.authorizeRequests() //开始请求权限配置
.antMatchers("/admin/**").hasRole("ROLE_ADMIN") //只有拥有ROLE_ADMIN角色的用户可以访问
.antMatchers("/user/**").hasAnyRole("ROLE_ADMIN","ROLE_USER") //拥有ROLE_ADMIN,ROLE_USER角色的用户可以访问
.anyRequest().authenticated(); //所有请求都需要认证后(登录后)才可访问
/**5.定制登录行为*/
http.formLogin() //定制登录操作
.loginPage("/login") //定制登录页面的访问地址
.defaultSuccessUrl("index") //定制登录成功后转向的页面
.failureUrl("/login?error") //指定登录失败后转向的页面
.permitAll()
.and()
.rememberMe() //开启cookie存储用户信息
.tokenValiditySeconds(12096000) //指定cookie有效期为1209600秒,即2个星期
.key("myKey") //指定cookie中的私钥
.and()
.logout() //定制注销行为
.logoutUrl("/custom-logout") //指定注销的URL路径
.logoutSuccessUrl("/logout-success") //指定注销成功后转向的页面
.permitAll();
}
@Override
public void configure(WebSecurity web) throws Exception{
super.configure(web);
}
}
业务方法CustomUserService:
import org.springframework.security.core.userdetails.UserDetailsService
public class CustomUserService implements UserDetailsService{
@Autowired
SysUserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException{
SysUser user = userRepository.findByUsername(username);
List<GrantedAuthority> authorities = new ArrayList<>();
authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
return new User(user.getUsername(),user.getPassword,authorities)
}
}
4. 安全处理方法
方法 | 用途 |
access(String) | Spring EL表达式结果为true时可以访问 |
anonymous() | 匿名可访问 |
denyAll() | 用户不能访问 |
fullyAuthenticated() | 用户完全认证可访问(非remember me下自动登录) |
hasAnyAuthority(String...) | 如果用户有参数,则其中任一权限可访问 |
hasAnyRole(String...) | 如果用户有参数,则其中任一角色可访问 |
hasAuthority(String) | 如果用户有参数,则其权限可访问 |
hasIpAddress(String) | 如果用户来自参数中的IP则可访问 |
hasRole(String) | 若用户有参数中的角色可访问 |
permitAll() | 用户可任意访问 |
rememberMe() | 允许通过remember-me登录的用户访问 |
authenticated() | 用户登录后可访问 |
5.spring boot 支持
主要通过SecurityAutoConfiguration和SecurityProperties来完成配置。SecurityAutoConfiguration导入了SpringBootWebSecurityConfiguration中的配置,其自动配置如下:
- 自动配置了一个内存用户,账号为user,密码在程序启动时出现
- 忽略/css,/js,/images和/favicon.ico等静态文件的拦截
- 自动配置的securityFilterChainRegistration的Bean
配置文件:
security.user.name=user #内存中的用户默认账号为user
security.user.password= #1默认用户的密码
security.user.role=USER #默认用户的角色
security.require-ssl=false #是否需要ssl支持
security.enable-csrf=false #是否开启“跨站请求伪造”支持,默认关闭
security.basic.enabled=true
security.basic.realm=Spring
security.basic.path= #/**
security.basic.authorize-mode=
security.filter-order=0
security.headers.xss=false
security.headers.cache=false
security.headers.frame=false
security.headers.content-type=false
security.headers.hsts=all
security.sessions=stateless
security.ignored= #用逗号隔开的无需拦截的路径
扩展配置:
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
}
三.