springsecuity的基本理解和使用
1.配置类中一些基本参数
@Bean
SecurityFilterChain filterChain(HttpSecurity http)
这个bean中进行配置,让整个springsecurity生效,在测试的时候,可以直接对bean注释掉,让整个security失效
1.1定义授权规则
http.authorizeRequests
可以使用lambda表达式进行设置,主要参数为路径+规则的设置
1.2重写处理器
未获得权限认证
implements AccessDeniedHandler
重定向
implements AuthenticationEntryPoint
登录失败
implements AuthenticationFailureHandler
登录成功
implements AuthenticationSuccessHandler
登出
implements LogoutSuccessHandler
session设置
implements SessionInformationExpiredStrategy
1.3动态rbac
对这个接口实现,返回 new AuthorizationDecision(bool)对象,通过5张表的查询,判断返回类型
可以限制url,权限
/**
* @param au,可以获得username
* @param obj 可以获得方法
* @retrun
*/
@Override
public AuthorizationDecision check(Supplier<Authentication> au, RequestAuthorizationContext obj)
在配置类中注册
http.authorizeHttpRequests(
authorize -> authorize
.anyRequest()
.access(rbacAccess)
);
1.4 使用jwt策略
类似过滤器链接口, 继承这个父类OncePerRequestFilter,重写方法,使用上下文进行校验
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
LoginUser loginUser = tokenManager.getLoginUser(request);
if (ObjectUtil.isNotNull(loginUser) && ObjectUtil.isNull(SecurityUtils.getAuthentication()))
{
tokenManager.verifyToken(loginUser);
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities());
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
}
chain.doFilter(request,response);
}
在配置类中选择添加链的添加位置
http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
2.常见上下文对象
2.1 SecurityContextHolder
储存Authentication对象
Authentication 对象包含以下属性:
- `Principal`:代表当前认证的用户,通常是一个 `UserDetails` 实例。implements UserDetails
- `Credentials`:认证时使用的凭证,如密码(通常只在认证过程中使用,之后会被清除)。
- `Authorities`:当前用户拥有的权限集合,通常是一个 `GrantedAuthority` 对象的集合。
2.2 userDetails
验证成功后,储存在Authentication的Principal中
这个对象可以继承重写接口,写可以之间使用security6提供的一个User实现类(建造者模式),这个对象在授权规则那一部分被调用,
.requestMatchers("/user/list").hasAuthority("USER_LIST")
.requestMatchers("/user/add").hasAuthority("USER_ADD")
或者1.3中的方法重写
2.3登录接口UserDetailsService接口中loadUserByUsername,创建userdetails
返回userDetails的实例,自动加入过滤链 .将数据库的password和输入创建的token进行对比,security中的失败用异常来捕捉
authentication = authenticationManager
.authenticate(new UsernamePasswordAuthenticationToken(username, password));
try
{
// 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
//对数据库查
authentication = authenticationManager
.authenticate(new UsernamePasswordAuthenticationToken(username, password));
}
catch (Exception e)
{
if (e instanceof BadCredentialsException)
{
throw new ServiceException("用户名密码错误");
}
else
{
throw new ServiceException(e.getMessage());
}
}
2.4* security的默认过滤链UsernamePasswordAuthenticationFilter
当前端传指定username和password字段时,会使用这个过滤链自动创建token
UsernamePasswordAuthenticationFilter会使用这些信息创建一个UsernamePasswordAuthenticationToken,并将其传递给认证管理器(AuthenticationManager)进行验证。token校验失败
2.5 UsernamePasswordAuthenticationToken
继承了 Authentication
AuthenticationManager进行验证(委派)成功后,返回一个Authentication的实例对象(UsernamePasswordAuthenticationToke),authentication的接口也发生变化
- 认证前创建的的token:
public UsernamePasswordAuthenticationToken(Object principal, Object credentials) {
super((Collection)null);
this.principal = principal;
this.credentials = credentials;
this.setAuthenticated(false);
}
-
认证成功后的token:
principal:此时通常是UserDetails实例,包含了用户的详细信息,如用户名、密码、权限等。credentials:通常设置为null,因为在认证成功后,出于安全考虑,不应该在Authentication对象中保留密码。authorities:包含了用户的权限集合,通常是GrantedAuthority对象的列表,定义了用户可以执行的操作或访问的资源。
public abstract class AbstractAuthenticationToken implements Authentication, CredentialsContainer {