Spring Security 基于 Spring 框架,提供了一套 Web 应用安全性的完整解决方案。
Web 应用的安全性包括用户认证(Authentication)和用户授权(Authorization)两个部分,这两点也是 Spring Security 重要核心功能。
SpringSecurity 特点:
自从有了 Spring Boot 之后,Spring Boot 对于 Spring Security 提供了自动化配置方案,可以使用更少的配置来使用 Spring Security。
因此,一般来说,常见的安全管理技术栈的组合是这样的:(只是一个推荐的组合而已,如果单纯从技术上来说,无论怎么组合,都是可以运行的)
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-securityartifactId>
dependency>
编写controller
@GetMapping("/hello")
public String hello() {
return "hello security";
}
访问http://localhost:8080/test/hello
就会需要认证
SpringSecurity本质是一个过滤器链
org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter
org.springframework.security.web.context.SecurityContextPersistenceFilter
org.springframework.security.web.header.HeaderWriterFilter
org.springframework.security.web.csrf.CsrfFilter
org.springframework.security.web.authentication.logout.LogoutFilter
org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter
org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter
org.springframework.security.web.savedrequest.RequestCacheAwareFilter
org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter
org.springframework.security.web.authentication.AnonymousAuthenticationFilter
org.springframework.security.web.session.SessionManagementFilter
org.springframework.security.web.access.ExceptionTranslationFilter
org.springframework.security.web.access.intercept.FilterSecurityInterceptor
SpringSecurity过滤器链中有几个比较重要的过滤器
是一个方法级的权限过滤器, 基本位于过滤链的最底部
源码getSecureObjectClass部分:
//此处说明 在这个之前还会有过滤器 当之前的过滤器放行了才会进行到这一步
//super.beforeInvocation(fi)表示查看之前的 filter 是否通过
InterceptorStatusToken token = super.beforeInvocation(filterInvocation);
try {
//表示真正的调用后台的服务
filterInvocation.getChain().doFilter(filterInvocation.getRequest(), filterInvocation.getResponse());
} finally {
super.finallyInvocation(token);
}
super.afterInvocation(token, (Object)null);
是个异常过滤器,用来处理在认证授权过程中抛出的异常
对/login 的 POST 请求做拦截,校验表单中用户名,密码
当什么也没有配置的时候,账号和密码是由Spring Security定义生成的。
而在实际项目中账号和密码都是从数据库中查询出来的。
所以我们要通过自定义逻辑控制认证逻辑。
如果需要自定义逻辑时,只需要实现UserDetailsService,接口即可
步骤:
// 表示把参数按照特定的解析规则进行解析
String encode(CharSequence rawPassword);
//表示验证从存储中获取的编码密码与编码后提交的原始密码是否匹配。
//如果密码匹配,则返回 true;如果不匹配,则返回 false。
//第一个参数表示需要被解析的密码。第二个参数表示存储的密码。
boolean matches(CharSequence rawPassword, String encodedPassword);
// 表示如果解析的密码能够再次进行解析且达到更安全的结果则返回 true,否则返回false。默认返回 false。
default boolean upgradeEncoding(String encodedPassword) {
return false;
}
spring.security.user.name=admin
spring.security.user.password=admin
使用 方法二 时 方法一 失效
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()//认证信息存储到内存中
.withUser("lucy")//用户名
.password(new BCryptPasswordEncoder().encode("123"))//用户密码(加密)
.roles("admin");//每个用户都配置角色(不能为空)
}
@Bean
//configure需要用到加密方式但默认没有 需要在容器的创建一个
PasswordEncoder password() {
return new BCryptPasswordEncoder();
}
}
config:
@Configuration
public class SecurityConfigTest extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(password());
}
@Bean
PasswordEncoder password() {
return new BCryptPasswordEncoder();
}
}
Service:
@Service("userDetailsService")
public class MyUserDetailsService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
List<GrantedAuthority> auths =
AuthorityUtils.commaSeparatedStringToAuthorityList("super");
//TODO :从查询数据库返回users对象,得到用户名和密码,返回
return new User("mary", new BCryptPasswordEncoder().encode("123"), auths);
}
}