微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

自定义Spring Security以获取可信空间

如何解决自定义Spring Security以获取可信空间

可信空间问题具有与匿名用户标识类似的解决方案(在研究时,我已经得出了这个结论。)

简短答案

受信任的空间并不需要授权,但没有 一个UserDetailsS​​ervice 会被调用,因为只使用的,AnonymousAuthenticationProvider并且AnonymousAuthenticationFilter认情况下。足以实现基于AnonymousAuthenticationFilter覆盖的自定义过滤器,createAuthenticationAnonymousAuthenticationFilter自定义一个CustomAnonymousAuthenticationFilter)替换认值():

    @组态
    公共静态类NoAuthConfigurationAdapter扩展了WebSecurityConfigurerAdapter {
        @Autowired
        私人UserDetailsS​​ervice userDetailsS​​ervice;
        @Autowired
        私有IdentifiableAnonymousAuthenticationFilter identifiableAnonymousAuthenticationFilter;

        @Override
        受保护的void configure(HttpSecurity http)抛出异常{
            http.anonymous()。authenticationFilter(identifiableAnonymousAuthenticationFilter);
            http.antMatcher(“ / **”)。authorizeRequests()
                    .anyRequest()。permitAll();
        }
    }

完整答案

我发现,如果未授权用户,则永远不会调用 *

 @零件
公共类IdentifiableAnonymousAuthenticationFilter扩展了AnonymousAuthenticationFilter {
    公共静态最终字符串KEY_IDENTIFIABLE_ANONYMOUS_AUTHENTICATION_FILTER
            =“ Key.IdentifiableAnonymousAuthenticationFilter”;
    @Autowired
    私人CustomUserDetailsS​​ervice userDetailsS​​ervice;
    @Autowired
    私有GrantedAuthorityService grantAuthorityService;
    私有AuthenticationDetailsS​​ource身份验证DetailsS​​ource
            = new WebAuthenticationDetailsS​​ource();

    public IdentifiableAnonymousAuthenticationFilter(){
        这个(KEY_IDENTIFIABLE_ANONYMOUS_AUTHENTICATION_FILTER);
    }

    public IdentifiableAnonymousAuthenticationFilter(String key){
        超级(密钥);
    }

    @Override
    受保护的身份验证createAuthentication(HttpServletRequest请求){
        AnonymousAuthenticationToken auth = new AnonymousAuthenticationToken(
                KEY_IDENTIFIABLE_ANONYMOUS_AUTHENTICATION_FILTER,
                userDetailsS​​ervice.loadCurrentUser(request),
                grantAuthorityService.getGrantedAuthoritiesForCurrentUser());
        auth.setDetails(authenticationDetailsS​​ource.buildDetails(request));
        返回认证;
    }
}

将其注入配置

@Configuration
public class IdentifyAnonymousConfigurationAdapter extends WebSecurityConfigurerAdapter {
    @Autowired
    private IdentifiableAnonymousAuthenticationFilter identifiableAnonymousAuthenticationFilter;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.anonymous().authenticationFilter(identifiableAnonymousAuthenticationFilter);
    // ... some other configurations
    }
}

现在看起来好多了,因为 identifiableAnonymousAuthenticationFilter 已注入 。请注意基于的配置WebSecurityConfigurerAdapter。如果您只有几个,并且其中一个不会设置customAnonymousAuthenticationFilter, 而是配置为早于 custom .., 您将获得AnonymousAuthenticationFilter的 认实例(认情况下配置WebSecurityConfigurerAdapter):

  受保护的最终HttpSecurity getHttp()引发异常{
      // ...
      http
        .csrf()。and()
        .addFilter(新的WebAsyncManagerIntegrationFilter())
        .exceptionHandling()。and()
        .headers()。and()
        .sessionManagement()。和()
        .securityContext()。and()
        .requestCache()。and()
        .anonymous()。和()
      // ...

如果应用程序已修复,我不会在乎,但是 早于 调用。然后 doFilter 放入 incorrect身份验证。

public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, servletexception {
    if(SecurityContextHolder.getContext().getAuthentication() == null) {
        SecurityContextHolder.getContext().setAuthentication(this.createAuthentication((HttpServletRequest)req));
        if(this.logger.isDebugEnabled()) {
            this.logger.debug("Populated SecurityContextHolder with anonymous token: '" + SecurityContextHolder.getContext().getAuthentication() + "'");
        }
    } else if(this.logger.isDebugEnabled()) {
        this.logger.debug("SecurityContextHolder not populated with anonymous token, as it already contained: '" + SecurityContextHolder.getContext().getAuthentication() + "'");
    }

    chain.doFilter(req, res);
}

因此,下一次为 *Authentication``if(SecurityContextHolder.getContext().getAuthentication() == null)

结果,提供配置非常有用,其中WebSecurityConfigurerAdapter使用魔术批注 修复配置以管理配置加载顺序。

警告

或者有人会想- doFilter添加无条件覆盖(这是 ):

    @Override
    公共无效doFilter(ServletRequest请求,ServletResponse资源,FilterChain链)
            引发IOException,servletexception {
        SecurityContextHolder.getContext()。setAuthentication(createAuthentication((HttpServletRequest)req));
        如果(logger.isDebugEnabled()){
            logger.debug(“带有匿名令牌的已填充SecurityContextHolder:”
                    + SecurityContextHolder.getContext()。getAuthentication()+“'”);
        }
        chain.doFilter(req,res);
    }

如果您需要通过处理授权的/已认证的用户来确保spring安全性,这是不可接受的,但是在某些情况下,这就足够了。

ps

解决方案的某些部分可以改进,但我希望这个想法总体上是明确的。

解决方法

服务在网关在受信任空间中运行之后(gateWay验证OAuth令牌,并仅向服务提供唯一的用户ID,否则它将重定向到身份验证服务)。

我想在服务中使用Spring Security来验证userId的权限。

所以我加了 CustomUserDetailsService

@Service(“ userDetailsS​​ervice”)
公共类CustomUserDetailsS​​ervice实现UserDetailsS​​ervice {
    @Autowired(必填=假)
    私有ContextSsoActiveProfileIdProvider contextSsoActiveProfileIdProvider;
    @Autowired
    私有GrantedAuthorityService grantAuthorityService;

    @Override
    公共用户loadUserByUsername(最终字符串用户名)抛出UsernameNotFoundException {
        //使用身份验证服务验证它,但没有令牌,仅用户ID,因此信任网关服务。
        返回新用户(
                String.valueOf(contextSsoActiveProfileIdProvider.getSsoActiveProfileId()),
                “ authenticatedWithGateWay”,
                allowedAuthorityService.getGrantedAuthoritiesForCurrentUser()
        );
    }
}

其中 contextSsoActiveProfileIdProvider.getSsoActiveProfileId() 返回uniqueUserId,
grantAuthorityService.getGrantedAuthoritiesForCurrentUser() 返回权限。

该服务在受信任区域中启动,因此我已通过以下方式配置了安全性:

@EnableWebSecurity
@组态
公共类SecurityConfiguration扩展了WebSecurityConfigurerAdapter {
    @Autowired
    私人UserDetailsS​​ervice userDetailsS​​ervice;

    @Override
    受保护的void configure(HttpSecurity http)抛出异常{
        http
                .authorizeRequests()
                .antMatchers(“ / **”)。permitAll();
    }

    @Override
    受保护的UserDetailsS​​ervice userDetailsS​​ervice(){
        返回userDetailsS​​ervice;
    }
}

我需要为所有用户提供免费接入(不触发登录报价)所有的URI(
http.authorizeRequests().antMatchers("/**").permitAll();),但它似乎抑制触发处理程序下一个注解@PreAuthorize@PreFilter@PostAuthorize@PostFilter

我想我在这里误以为http.authorizeRequests().antMatchers("/**").permitAll();是其他配置部分。

更多问题症状:

  • CustomUserDetailsService.loadUserByUsername(..) 从不叫;
  • 在REST API上,部分@AuthenticationPrincipal User activeUser为null
  • 在REST API上,部分Principal principal也为null

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。