0

我的 spring boot (2.2.4) 应用程序使用 siteminder 作为身份验证提供程序。成功认证后,站点管理员在 Http 标头中发送用户详细信息(角色)。在应用程序内部,我需要使用 spring security 进行基于角色的授权。这是我正在关注的参考文档 - https://docs.spring.io/spring-security/site/docs/5.0.x/reference/html/preauth.html

我的 spring-security.xml 看起来像这样。

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:security="http://www.springframework.org/schema/security"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/security
        https://www.springframework.org/schema/security/spring-security.xsd">

    <security:http>
        <!-- Additional http configuration omitted -->
        <security:csrf disabled="true"/>
        <security:intercept-url pattern="/**" access="hasRole('ROLE_ABC')"/>
        <security:custom-filter position="PRE_AUTH_FILTER" ref="siteminderFilter" />
    </security:http>

    <bean id="siteminderFilter" class="org.springframework.security.web.authentication.preauth.RequestHeaderAuthenticationFilter">
        <property name="principalRequestHeader" value="SM_USER"/>
        <property name="authenticationManager" ref="authenticationManager" />
    </bean>

    <bean id="preauthAuthProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
        <property name="preAuthenticatedUserDetailsService">
            <bean id="userDetailsServiceWrapper"
                  class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
                <property name="userDetailsService" ref="userDetailsService"/>
            </bean>
        </property>
    </bean>

    <bean id="userDetailsService" class="com.mycode.service.SCPMUserDetailsService"/>

    <security:authentication-manager alias="authenticationManager">
        <security:authentication-provider ref="preauthAuthProvider" />
    </security:authentication-manager>
</beans>

如何创建一个 Java 配置文件,该文件将包含 Spring Boot 应用程序的上述安全性。

我开始了这样的事情,需要在上面的 xml 文件中注入所有的部分。

@EnableWebSecurity
@Order(SecurityProperties.BASIC_AUTH_ORDER - 10)
public class SecurityConfigurer extends WebSecurityConfigurerAdapter {

    @Autowired
    private MyUserDetailsService myUserDetailsService;


    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(myUserDetailsService);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()// Disable for GraphIQL to work locally
                .antMatcher("/**")
                .authorizeRequests()
                .antMatchers("/healthcheck/**").permitAll()
                .antMatchers("/scpm/**").permitAll()
                .antMatchers("/approvers/**").hasRole("APPROVER")
                .antMatchers("/departments/**").hasRole("ADMIN")
                .anyRequest().authenticated()
                .and().httpBasic();
    }
}
4

1 回答 1

0

Spring Security 参考文档不提供用于 SiteMinder 集成的 Java 代码。它只是为非 Spring Boot 应用程序提供 xml 配置。这是可用于任何 Spring Boot 应用程序的 Java 代码。

@EnableWebSecurity
@Configuration
@Order(SecurityProperties.BASIC_AUTH_ORDER - 10)
public class SecurityConfigurer extends WebSecurityConfigurerAdapter {

    @Autowired
    private MyUserDetailsService userDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService);
        auth.authenticationProvider(preAuthenticatedAuthenticationProvider());
    }

    @Bean
    public RequestHeaderAuthenticationFilter siteminderFilter() throws Exception {
        RequestHeaderAuthenticationFilter filter = new RequestHeaderAuthenticationFilter();
        filter.setPrincipalRequestHeader("SM_USER");
        filter.setAuthenticationManager(this.authenticationManager());
        return filter;
    }

    @Bean
    public PreAuthenticatedAuthenticationProvider preAuthenticatedAuthenticationProvider() {
        PreAuthenticatedAuthenticationProvider preauthAuthProvider = new PreAuthenticatedAuthenticationProvider();
        preauthAuthProvider.setPreAuthenticatedUserDetailsService(userDetailsByNameServiceWrapper());
        return preauthAuthProvider;
    }

    @Bean
    public UserDetailsByNameServiceWrapper userDetailsByNameServiceWrapper() {
        UserDetailsByNameServiceWrapper userDetailsServiceWrapper = new UserDetailsByNameServiceWrapper();
        userDetailsServiceWrapper.setUserDetailsService(userDetailsService);
        return userDetailsServiceWrapper;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .addFilter(siteminderFilter())
                .csrf().disable()// Disable for GraphIQL to work locally
                .antMatcher("/**")
                .authorizeRequests()
                .antMatchers("/healthcheck/**").permitAll()
                .antMatchers("/approvers/**").hasRole("APPROVER")
                .antMatchers("/admin/**").hasRole("ADMIN")
                .anyRequest().authenticated()
                .and().httpBasic();
    }
}

这是自定义的 UserDetailsS​​ervice。

@Service
public class MyUserDetailsService implements UserDetailsService {

    private Logger logger = LoggerFactory.getLogger(SCPMUserDetailsService.class);

    @Autowired
    private HttpServletRequest request;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException{
        HttpServletRequest request  =
                ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
                        .getRequest();
        String csgroups = "";
        Collection<GrantedAuthority> auth = new ArrayList<>();

        try {
            username = request.getHeader("SM_USER");
        } catch (Exception ex){
            logger.trace("SM_USER not found in Request Http Headers");
            ex.printStackTrace();
        }

        try {
            csgroups = request.getHeader("ROLES");;
        } catch (Exception ex){
            logger.trace("CSGROUPS not found in Request Http Headers");
            ex.printStackTrace();
        }

        //Roles
        if(csgroups != null) {
            StringTokenizer st = new StringTokenizer(csgroups, "^");

            while (st.hasMoreElements()) {
                GrantedAuthority authority = new SimpleGrantedAuthority("ROLE_" + st.nextToken());
            }
        }
        return new User(username, "", true, true, true, true,auth);
    }


    @Bean
    public PasswordEncoder passwordEncoder() {
        return NoOpPasswordEncoder.getInstance();
    }
}
于 2020-07-22T14:38:47.637 回答