无法使用预身份验证为Spring Boot / Security App配置FORM身份验证

时间:2014-10-29 15:46:54

标签: spring-security tomcat7 spring-boot

我已经成功配置了一个Spring启动应用程序,以使用Spring安全预身份验证框架,依靠Tomcat 7容器从tomcat-users.xml文件进行身份验证。我还能够添加自定义AuthenticationUserDetailsS​​ervice以将权限映射到容器验证的用户(我不想管理容器中的应用程序角色)。我需要一段时间才能完成Java配置,但我把它全部用作魅力......但只有当我使用BASIC身份验证时(在web.xml中配置)。当我尝试转换为FORM身份验证时,过滤器链中间出现问题。

在web.xml中配置的登录表单正在呈现(使用this example中的themeleaf)。我还从日志中看到用户成功进行了身份验证,这意味着正在按预期与容器进行通信。我还看到J2eePreAuthenticatedProcessingFilter获取J2EE主体并调用自定义AuthenticationUserDetailsS​​ervice来映射角色。但是,在日志中稍微向下看,HttpSessionSecurityContextRepository会为SPRING_SECURITY_CONTEXT获取一个空对象(同时通过过滤器链来获取' / login'?)。结果,似乎再也没有引用J2EE主体,随后创建了一个带有匿名标记的SecurityContextHolder'。尽管事实上我发现它找到了[permitAll]'我已经为' / login'配置了url(在Spring配置中)。

以下是我的web.xml的摘录:

    <!-- Define a Security Constraint on this Application -->
    <security-constraint>
        <web-resource-collection>
            <web-resource-name>Secured (entire app)</web-resource-name>
            <url-pattern>/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>USER</role-name>
        </auth-constraint>
    </security-constraint>

    <!-- Define the Login Configuration for this Application -->
    <login-config>
        <auth-method>FORM</auth-method>
        <form-login-config>
            <form-login-page>/login</form-login-page>
            <form-error-page>/login?error</form-error-page>
        </form-login-config>
    </login-config>

    <!-- Security roles referenced by this web application -->
    <security-role>
        <description>
            The role that is required to access the application
        </description>
        <role-name>USER</role-name>
    </security-role>

因此,我的tomcat-users.xml有一个用户名为&#39; user&#39;以及&#39; USER&#39;的作用。我不会先在&#39; ROLE _&#39;因为我不想将任何角色映射到应用程序中。我使用我的自定义AuthenticationUserDetailsS​​ervice。

这是我的主配置文件。注意,我还有另一个实现SpringBootServletInitializer的类,并将SpringApplicationBuilder配置为指向这个类:

@EnableAutoConfiguration
@ComponentScan
@EnableGlobalMethodSecurity(securedEnabled = true)
public class MyApplicationConfig extends WebMvcConfigurerAdapter {

    @Controller
    protected static class HomeController {

        // ROLE_MYAPP_USER is mapped to all authenticated users by custom AuthenticationUserDetailsService
        @RequestMapping({"/", "/about", "/profile"})
        @Secured("ROLE_MYAPP_USER")
        public ModelAndView index(@CurrentUser User user) {
            Map<String, Object> model = new HashMap<>();
            model.put("currentUser", user);
            //noinspection SpringMVCViewInspection
            return new ModelAndView("index", model);
        }

    }

    public static void main(String[] args) throws Exception {
        new SpringApplicationBuilder(VodConsoleApplication.class).run(args);
    }

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/login").setViewName("login");
    }

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        argumentResolvers.add(new CurrentUserHandlerMethodArgumentResolver());
    }


    @Bean
    public ApplicationSecurity applicationSecurity() {
        return new ApplicationSecurity();
    }

    @Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
    protected static class ApplicationSecurity extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable();

        http
                .authorizeRequests()
                .antMatchers("/login").permitAll()
                .antMatchers("/error").permitAll()
                .antMatchers("/css/**").permitAll()
                .antMatchers("/img/**").permitAll()
                .antMatchers("/js/**").permitAll()
                .antMatchers("/partials/**").permitAll()
                .antMatchers("/vendor/**").permitAll()
                .anyRequest().authenticated()
                .and()
                .jee()
                .authenticatedUserDetailsService(new InMemoryUserDetailsService());
        http.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessUrl("/");

        }
    }
}

还有一个发布到/ j_security_check的login.html表单。如果您需要,请告诉我,虽然它非常简单,并且(从日志中)显示它正在运行。

同样,一切都可以完美地与web.xml中配置的BASIC身份验证配合使用。一旦我转到FORM,我就会在过滤器处理链的中间删除J2EE主体。

想法?可能是我需要以不同方式配置我的web.xml安全性约束吗?

任何帮助都会非常感激。

1 个答案:

答案 0 :(得分:0)

解决。事实证明,我还需要为我的所有公众添加网址模式。资源进入web.xml。具体来说,javascript(在&#39;供应商&#39; js&#39;目录中),css,img等。这是我更新的web.xml:

<security-constraint>
    <web-resource-collection>
        <web-resource-name>Public resources</web-resource-name>
        <url-pattern>/vendor/*</url-pattern>
        <url-pattern>/js/*</url-pattern>
        <url-pattern>/css/*</url-pattern>
        <url-pattern>/img/*</url-pattern>
        <url-pattern>/partials/*</url-pattern>
    </web-resource-collection>
</security-constraint>
<security-constraint>
    <web-resource-collection>
        <web-resource-name>Secured (entire app)</web-resource-name>
        <url-pattern>/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
        <role-name>USER</role-name>
    </auth-constraint>
</security-constraint>

<!-- Define the Login Configuration for this Application -->
<login-config>
    <auth-method>FORM</auth-method>
    <form-login-config>
        <form-login-page>/login</form-login-page>
        <form-error-page>/login?error</form-error-page>
    </form-login-config>
</login-config>
<!-- Security roles referenced by this web application -->
<security-role>
    <description>
        The role that is required to access the application
    </description>
    <role-name>USER</role-name>
</security-role>