为了账号安全,请及时绑定邮箱和手机立即绑定

Spring Security 中的身份验证和授权有什么区别?

Spring Security 中的身份验证和授权有什么区别?

Qyouu 2023-10-19 15:03:24
我正在开发一个 java spring boot 项目,我正在尝试使用 JWT 设置 spring security 以进行用户身份验证,我正在关注的教程(以及我在互联网上找到的许多教程和项目)讨论了两个部分-认证和授权。在大多数教程中,有两个过滤器类,一个处理身份验证,另一个处理授权!(我发现有些只有一个扩展OncePerRequestFilter类的类)。在那些具有两个过滤器类的项目中,身份验证过滤器类扩展了UsernamePasswordAuthenticationFilter类。授权类扩展BasicAuthenticationFilter类。有没有一种方法,我只能在我的项目中使用身份验证部分,或者我应该使用这两个类在 Spring Security 中设置用户身份验证?任何解释将不胜感激。
查看完整描述

2 回答

?
Cats萌萌

TA贡献1805条经验 获得超9个赞

有没有一种方法,我只能在我的项目中使用身份验证部分,或者我应该使用这两个类在 Spring Security 中设置用户身份验证?

不,不存在只有身份验证部分的概念,您对 Spring Security 的看法是错误的,Spring Security 的全部内容都与使用默认配置或实现自定义配置有关。(AuthenticationFilters、、AuthenticationProvidersAuthenticationToken



Spring security 是关于身份验证和授权的,Spring security 是通过在 web.xml 中声明一个过滤器 DelegatingFilterProxy 来配置的(在 Spring boot 中,它将通过自动配置来完成)。


Spring 安全性在代理过滤器或 Spring 托管 bean 方面将WALL ( HttpFireWall )放置在您的应用程序之前。如果请求在身份验证和授权部分都成功,则可以到达您的应用程序。

1. 身份验证就是对用户的身份识别。

它将经历

  • 验证凭证或

  • 验证授权标头内容或

  • 验证与请求关联的 cookie(JSESSIONID cookie),即会话

  • 如果以上都不匹配,则用户被识别为匿名。

在此步骤中将Authentication 创建对象。从 auth 对象你可以得到

  • 详细信息对象(有关身份验证请求的其他详细信息)

  • 主要对象UserDetailsAuthenticatedPrincipalPrincipal

  • 凭据(通常是密码,但可以是与 相关的任何内容AuthenticationManager

  • 授予权限的集合

  • 和一个布尔值已验证

2. 授权就是访问决策。

FilterSecurityInterceptor过滤器链中几乎最后一个会Authentication从过滤器链中获取对象SecurityContext并获得授予的权限列表(授予的角色),并且它将决定是否允许该请求到达所请求的资源,决定是通过与允许在HttpSecurityConfiguration.

考虑例外情况 401-UnAuthorized 和 403-Forbidden。这些决定将在过滤器链的最后完成。
401-UnAuthorized:未经身份验证的用户尝试访问受保护的资源。
403-Forbidden:经过身份验证的用户尝试访问受限资源。
未经身份验证的用户将被允许访问非受限资源,并且他不会收到 UnAuthorized 错误,但它是由为未经身份验证的用户AnonymousAuthenticationFilter设置权限来处理的。ROLE_ANONYMOUS

注意
下面给出了过滤器排序。其中,
身份验证为 @order-4
授权为 @Order-9(Last)

Spring Security有
几个区域,您定义的模式会针对传入请求进行测试,以便决定如何处理请求。当FilterChainProxy决定应通过哪个过滤器链以及决定FilterSecurityInterceptor对请求应用哪些安全约束时,就会发生这种情况。根据您定义的模式进行测试时,了解机制是什么以及使用什么 URL 值非常重要。

过滤器排序
过滤器在链中定义的顺序非常重要。无论您实际使用哪个过滤器,顺序都应如下:
1. ChannelProcessingFilter,因为它可能需要重定向到不同的协议
2. SecurityContextPersistenceFilter,因此可以在 Web 请求开始时在 SecurityContextHolder 中设置 SecurityContext,并且对 SecurityContext 的任何更改都可以在HttpSessionWeb 请求结束时复制到(准备用于下一个 Web 请求)
3. ConcurrentSessionFilter,因为它使用该SecurityContextHolder功能,但需要更新SessionRegistry以反映来自主体的正在进行的请求
4.身份验证处理机制UsernamePasswordAuthenticationFilter、CasAuthenticationFilter、BasicAuthenticationFilter 等 - 以便可以修改 SecurityContextHolder 以包含有效的身份验证请求令牌
5. SecurityContextHolderAwareRequestFilter如果您使用它来将 Spring Security 感知安装HttpServletRequestWrapper到您的 servlet 容器中
6. RememberMeAuthenticationFilter,以便如果没有早期身份验证处理机制更新了SecurityContextHolder,并且请求提供了一个 cookie,使记住我服务能够发生,一个合适的记住的 Authentication 对象将被放置在那里
7. AnonymousAuthenticationFilter,这样,如果没有早期的身份验证处理机制更新SecurityContextHolder,一个匿名的 Authentication 对象将被放置
8.捕获ExceptionTranslationFilter任何 Spring Security 异常,以便返回 HTTP 错误响应或AuthenticationEntryPoint启动适当的响应
9.FilterSecurityInterceptor保护 Web URI 并在访问被拒绝时引发异常

只是为了提供一些 Spring Security 中过滤器的想法

https://img1.sycdn.imooc.com/6530faf70001a5ee06420695.jpg

查看完整回答
反对 回复 2023-10-19
?
PIPIONE

TA贡献1829条经验 获得超9个赞

你必须写你的 userDetial 来告诉 spring 当前的用户授权和配置

public class MyUserDetails implements UserDetails {


/**

 * 

 */

private static final long serialVersionUID = 1L;

private User user;


public MyUserDetails(User user) {

    this.user = user;

}


@Override

public String getUsername() {

    return user.getLogin();

}


@Override

public String getPassword() {

    return user.getPassword();

}


@Override

public Collection<? extends GrantedAuthority> getAuthorities() {

    return user.getGrantedAuthorities();

}


@Override

public boolean isAccountNonExpired() {

    return user.getActivated();

}


@Override

public boolean isAccountNonLocked() {

    return user.getActivated();

}


@Override

public boolean isCredentialsNonExpired() {

    return user.getActivated();

}


@Override

public boolean isEnabled() {

    return user.getActivated();

}


你的过滤器可能是这样的

public class JWTFilter extends GenericFilterBean {


private TokenProvider tokenProvider;


public JWTFilter(TokenProvider tokenProvider) {

    this.tokenProvider = tokenProvider;

}


@Override

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)

    throws IOException, ServletException {

    HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;

    String jwt = resolveToken(httpServletRequest);

    if (StringUtils.hasText(jwt) && this.tokenProvider.validateToken(jwt)) {

        Authentication authentication = this.tokenProvider.getAuthentication(jwt);

        SecurityContextHolder.getContext().setAuthentication(authentication);

    }

    filterChain.doFilter(servletRequest, servletResponse);

}


private String resolveToken(HttpServletRequest request){

    String bearerToken1 = RequestUtil.getTokenFromHeader(request);

    if (bearerToken1 != null) return bearerToken1;

    String jwt = request.getParameter(JWTConfigurer.AUTHORIZATION_TOKEN);

    if (StringUtils.hasText(jwt)) {

        return jwt;

    }

    return null;

}

}

你必须将你的 userDetailService 更改为 spring 知道如何laod你的用户

@Component("userDetailsService")

public class DomainUserDetailsService implements UserDetailsService {


private final Logger log = LoggerFactory.getLogger(DomainUserDetailsService.class);


private final UserRepository userRepository;


public DomainUserDetailsService(UserRepository userRepository) {

    this.userRepository = userRepository;

}


@Override

@Transactional

public UserDetails loadUserByUsername(final String login) {

    log.debug("Authenticating {}", login);


    String lowercaseLogin = login.toLowerCase(Locale.ENGLISH);

    Optional<User> userByLoginFromDatabase = userRepository.findOneWithRolesByLogin(lowercaseLogin);

    return userByLoginFromDatabase.map(user -> new MyUserDetails(user))

        .orElseThrow(() -> new UsernameNotFoundException("User " + lowercaseLogin + " was not found in the database"));


}


}


查看完整回答
反对 回复 2023-10-19
  • 2 回答
  • 0 关注
  • 50 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信