簡體   English   中英

Spring Security 上下文中的身份驗證和授權有什么區別?

[英]What is the difference between authentication and authorization in context of Spring Security?

I'm working on a java spring boot project which I'm trying to get spring security set up for user authentication with JWT, the tutorial I'm following(and also many tutorials and projects I found on the internet) talks about two sections -身份驗證和授權

在大多數教程中,有兩個過濾器類,一個處理身份驗證,另一個處理授權! (有些我發現只有一個 class 擴展OncePerRequestFilter類)。

在具有兩個過濾器類的項目中,身份驗證過濾器 class 擴展了UsernamePasswordAuthenticationFilter class。 授權 class 擴展了BasicAuthenticationFilter class。

有沒有辦法我只能在我的項目中使用身份驗證部分,或者我應該使用這兩個類在 spring 安全性中設置用戶身份驗證?

任何解釋將不勝感激。

有沒有辦法我只能在我的項目中使用身份驗證部分,或者我應該使用這兩個類在 spring 安全性中設置用戶身份驗證?

不,沒有僅身份驗證部分的概念,您對 spring 安全性有錯誤的認識,spring 安全性都是關於使用默認配置或通過實施自定義配置的配置。 ( AuthenticationFiltersAuthenticationProvidersAuthenticationToken等)


Spring security is all about authentication and authorization, Spring security is configured by declaring a filter DelegatingFilterProxy in web.xml(In Spring boot it will be done by auto configuration).

Spring 安全性根據代理過濾器或 spring 托管 bean 在您的應用程序之前放置一個WALL ( HttpFireWall )。 如果在身份驗證和授權部分都成功,請求可以到達您的應用程序。

1. 認證就是對用戶的識別。

它會經歷

  • 驗證憑據或
  • 驗證授權 header 內容或
  • 驗證與請求關聯的 cookie(JSESSIONID cookie),即 session
  • 如果以上均不匹配,則將用戶標識為匿名用戶。

在此步驟中,將創建Authentication object。 從認證 object 你可以得到

  • 詳細信息 object (有關身份驗證請求的其他詳細信息)
  • 主體 objectUserDetailsAuthenticatedPrincipalPrincipal
  • 憑據(通常是密碼,但可以是與AuthenticationManager相關的任何內容)
  • grantAuthorites的集合
  • 和一個 boolean認證

2. 授權就是訪問決策。

FilterSecurityInterceptor幾乎排在過濾器鏈的最后,它從SecurityContext獲取Authentication object 並獲得授權權限列表(授予的角色),它將決定是否允許此請求到達請求的資源,決定由與 HttpSecurityConfiguration 中配置的允許HttpSecurityConfiguration匹配。

考慮例外 401-UnAuthorized 和 403-Forbidden。 這些決定將在過濾器鏈的最后完成
401-UnAuthorized :未經身份驗證的用戶試圖訪問受保護的資源。
403-Forbidden :經過身份驗證的用戶嘗試訪問受限資源。
未經身份驗證的用戶將被允許訪問非受限資源,並且他不會收到 UnAuthorized 錯誤,但它由AnonymousAuthenticationFilter處理,該過濾器為未經身份驗證的用戶設置權限ROLE_ANONYMOUS

筆記
下面給出了過濾器排序。 在哪里,
身份驗證是@order-4
授權是@Order-9(Last)

來自文檔
Spring 安全性有幾個區域,您定義的模式將針對傳入請求進行測試,以確定應如何處理請求。 FilterChainProxy決定一個請求應該通過哪個過濾器鏈時,以及當FilterSecurityInterceptor決定哪些安全約束應用於請求時,就會發生這種情況。 在針對您定義的模式進行測試時,了解機制是什么以及使用什么 URL 值非常重要。

過濾器排序
過濾器在鏈中定義的順序非常重要。 無論您實際使用的是哪種過濾器,順序應如下所示:
1. ChannelProcessingFilter ,因為它可能需要重定向到不同的協議
2. SecurityContextPersistenceFilter , so a SecurityContext can be set up in the SecurityContextHolder at the beginning of a web request, and any changes to the SecurityContext can be copied to the HttpSession when the web request ends (ready for use with the next web request)
3. ConcurrentSessionFilter ,因為它使用SecurityContextHolder功能但需要更新SessionRegistry以反映來自主體的正在進行的請求
4.身份驗證處理機制- UsernamePasswordAuthenticationFilter 、 CasAuthenticationFilter 、 BasicAuthenticationFilter 等 - 以便可以修改 SecurityContextHolder 以包含有效的身份驗證請求令牌
5. SecurityContextHolderAwareRequestFilter ,如果您使用它來將 Spring 安全感知HttpServletRequestWrapper安裝到您的 servlet 容器中
6. RememberMeAuthenticationFilter ,因此如果沒有更早的身份驗證處理機制更新SecurityContextHolder ,並且請求提供了一個啟用 remember-me 服務的 cookie,則將在那里放置一個合適的記憶身份驗證 object
7. AnonymousAuthenticationFilter ,這樣如果之前的認證處理機制沒有更新SecurityContextHolder ,一個匿名認證 object 就會放在那里
8. ExceptionTranslationFilter ,捕獲任何 Spring 安全異常,以便可以返回 HTTP 錯誤響應或可以啟動適當的AuthenticationEntryPoint
9. FilterSecurityInterceptor ,用於保護 web URI 並在訪問被拒絕時引發異常

只是為了介紹 spring 安全性中的過濾器

在此處輸入圖像描述

最后,如果您不熟悉 spring 安全性。 我的建議是嘗試最多的示例,並在調試日志上花費更多時間並嘗試理解流程。

你必須寫你的 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 知道如何讓您的用戶

@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"));

}

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM