繁体   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