簡體   English   中英

如何在 Spring Security 中添加授權過濾器來驗證令牌並設置安全上下文?

[英]How to add a authorization filter to validate token and set security context in spring security?

我有一個使用 spring security 4 的 spring MVC 應用程序,我想根據請求中的 jwt 令牌添加授權。 我需要在過濾器中做的是

  1. 從請求頭中獲取令牌
  2. 將令牌發送到外部 API 並獲取用戶詳細信息
  3. 在安全上下文中設置獲取的詳細信息

但是當我啟動應用程序時,我收到一條錯誤消息,指出An AuthenticationManager is required 我不確定 UserDetails 服務如何適用於我的用例。 因此,我添加了一個虛擬返回值進行測試,因為沒有 UserDetailsS​​ervice 應用程序將無法工作。 對此有什么想法嗎?

Spring 安全配置類

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(
  prePostEnabled = true
)
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
@Qualifier("applicationUserService")
UserDetailsService userDetailsService;

@Override
public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
  SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
  authenticationManagerBuilder
    .userDetailsService(userDetailsService)
    .passwordEncoder(bCryptPasswordEncoder());
}

@Override
protected void configure(HttpSecurity http) throws Exception {
  http.csrf().disable().authorizeRequests()
    .antMatchers(HttpMethod.GET, "/home").hasAnyRole("ADMIN")
    .antMatchers(HttpMethod.GET, "/login").hasAnyRole("ADMIN")
    .anyRequest().authenticated()
    .and()
    .addFilter(new AuthorizationFilter(authenticationManager()))
    .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}

@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}

授權過濾器類

public class AuthorizationFilter extends BasicAuthenticationFilter {

private static final Logger LOGGER = LoggerFactory.getLogger(AuthorizationFilter.class);

public AuthorizationFilter(AuthenticationManager authenticationManager) {
  super(authenticationManager);
}

@Override
protected void doFilterInternal(HttpServletRequest req, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
  LOGGER.info("Request Info : {}", req.getRequestURI());
  // get token
  // fetch details from external API
  // set security context
  List<GrantedAuthority> authorities = new ArrayList<>();
  authorities.add((GrantedAuthority) () -> "ROLE_ADMIN");
  SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken("user1", null, authorities));
  LOGGER.info("security context principle:{}", SecurityContextHolder.getContext().getAuthentication().getPrincipal().toString());
  LOGGER.info("authorities context:{}", SecurityContextHolder.getContext().getAuthentication().getAuthorities().toString());

  chain.doFilter(req, response);
}

UserDetailsS​​ervice 實現

@Service
@Qualifier("applicationUserService")
public class ApplicationUserServiceImpl implements UserDetailsService {

  @Override
  public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
    return new User("sidath", "123", emptyList());
  }
}

試試這個步驟

  1. 定義一個AbstractAuthenticationProcessingFilter來評估請求和返回令牌。

public class AwesomeFilter extends AbstractAuthenticationProcessingFilter {
    
    public AuthorizationFilter () {
       super(new AntPathRequestMatcher("/your_post_url", "POST"));
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) {
        
       // Evaluate request...
    
       // Build your custom authentication token with the info
       AwesomeToken token = new AwesomeToken();

       // Authenticate token with authentication manager
        return getAuthenticationManager().authenticate(token);
    }
  1. 定義一個AuthenticationProvider來支持你的AwesomeToken Spring Security 將嘗試“支持”這一點。
public class AwesomeProvider implements AuthenticationProvider {
    
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {

      // Evaluate your custom token
      // Call your API, etc

      // Build your user authentication token details with authorities
         Collection<? extends GrantedAuthority> auths = Collections.singletonList(new 
                SimpleGrantedAuthority("ROLE_ADMIN"));
         AwesomeUserToken token = new AwesomeUserToken(auths);

      // Return user token
         return token;
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return (AwesomeToken.class.isAssignableFrom(authentication));
    }
  1. 在 Spring Security Config 中注冊類。
    @Override
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth
           .authenticationProvider(new AwesomeProvider());
    }

    @Override
    public void addFilters(HttpSecurity http, AuthenticationManager authenticationManager) throws Exception {

        AwesomeFilter filter = new AwesomeFilter();
        filter.setAuthenticationManager(authenticationManager);
        http
            .addFilterAfter(filter, UsernamePasswordAuthenticationFilter.class);
    }

最后,當 Spring Security 檢測到帶有過濾器的請求時,它將嘗試支持提供者,然后返回具有所需權限的令牌。

暫無
暫無

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

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