Spring Boot 转成war包后,spring security就不生效了

古岁 发布于 2017/06/29 10:37
阅读 510
收藏 0
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {


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

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().anyRequest().authenticated()
                .and()
                .formLogin()
                .loginPage("/login").permitAll();
    }

    private final SubjectSecurityService subjectSecurityService;
    private final SubjectPasswordEncoder subjectPasswordEncoder;

    @Autowired
    public SecurityConfiguration(SubjectSecurityService subjectSecurityService, SubjectPasswordEncoder subjectPasswordEncoder) {
        this.subjectSecurityService = subjectSecurityService;
        this.subjectPasswordEncoder = subjectPasswordEncoder;
    }
}

这是我的配置,这个配置在jar模式下是可以正常工作的,但是改成war之后就不完全生效了。

具体的问题就是,访问所有页面会重定向到“/login”页面,但是点击登录提交表单之后还是重定向到“/login”,并且没有执行认证,没有执行userDetailsService.loadUserByUsername()方法,也没有执行PasswordEncoder。而是直接重定向“login”页面,而且没有携带任何error信息。我的login controller是只支持get请求的。如下:

    @GetMapping("/login")
    public ModelAndView login() {
        ModelAndView mav = new ModelAndView("login");
        Object e = request.getSession().getAttribute("SPRING_SECURITY_LAST_EXCEPTION");
        if (e != null) {
            mav.addObject("errorMessage", "用户名或密码错误");
        }
        return mav;
    }

转换war我只修改了pom.xml:

<packaging>war</packaging>
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-tomcat</artifactId>
   <scope>provided</scope>
</dependency>

和添加了SpringBootServletInitializer子类:

public class AppServletInitializer extends SpringBootServletInitializer {
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(App.class);
    }
}

如果我改回jar的方式,依然是可以正常工作的。

我想了解是什么原因,导致了原本在jar包下能正常工作的配置,到了war包下就失效了。

求各位大神们解答!

 

------------------------------补充--------------------------------

是这样的,我的登录页面是没有添加csrf token的,所以在我预计的正常情况下(jar包),点击登录应该会出现这样一个页面:

而且在war包下,点击登录却直接重定向了登录页,并没有出现错误页面。

然后我进行了调试,发现当我点击登录的时候,无论是在jar包还是war包下,AccessDeniedHandlerImpl类都会抛出response.sendError(),如图:

会抛出关于csrf的403错误。

所以现在的问题是,如何捕获这个异常,然后在一个自定义的error页面中将错误展示出来?

 

加载中
0
fly冬冬
fly冬冬
permitAll().antMatchers("/**") 
后面加个匹配看看
0
湃大星
湃大星

同上你后面加上个匹配试试看

自动切管机      www.jushunjixie.com

0
古岁
古岁

问题已经解决了,自问自答一下:

产生这个一直重定向到登录页的原因,是因为我没有经过认证,而没有传递csrf token又导致我无法进行认证(无法提交请求,请求会因为没有csrf token被拒绝),拒绝之后,因为没有认证又回到登录页,就成了这个死循环。所以,加上csrf token就可以进行认证流程了,认证成功后,如果没有权限,就会返回403页面。

那么为什么在jar包下就可以返回默认的403错误页面呢?这个我不知道,也许在jar下,用户被认证成匿名用户了吧。希望大神们来解释一下。

返回顶部
顶部