【问题标题】:Thymeleaf and Spring boot and Spring security not workingThymeleaf 和 Spring 引导以及 Spring 安全性不起作用
【发布时间】:2019-07-27 14:14:44
【问题描述】:

我正在尝试将 thymeleaf、spring security 和 spring boot 一起运行,但我不确定如何将它们集成在一起,因为我在 spring security 阻止静态的 href 等方面遇到了一些问题。

问题是提交登录后它没有通过安全配置的成功处理程序,所以我认为视图没有正确映射。

SecurityConfig 如下所示:

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private static final Logger logger = LogManager.getLogger(SecurityConfig.class);

    @Autowired
    private LoggingAccessDeniedHandler accessDeniedHandler;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers(
                        "/",
                        "/js/**",
                        "/css/**",
                        "/img/**",
                        "/webjars/**").permitAll()
                .antMatchers("/user/**").hasRole("USER")
                .anyRequest().authenticated()
            .and()
            .formLogin()
                .loginPage("/login")
                .successHandler(myAuthenticationSuccessHandler())
                .permitAll()
            .and()
            .logout()
                .invalidateHttpSession(true)
                .clearAuthentication(true)
                .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
                .logoutSuccessUrl("/login?logout")
                .permitAll()
            .and()
            .exceptionHandling()
                .accessDeniedHandler(accessDeniedHandler);
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web
            .ignoring()
            .antMatchers("/resources/**", "/static/**", "/css/**", "/js/**", "/images/**","/vendor/**","/fonts/**");
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        logger.info("configuring");
        auth.inMemoryAuthentication()
            .withUser("user").password("password").roles("USER")
            .and()
            .withUser("manager").password("password").roles("MANAGER");
    }

    @Bean
    public AuthenticationSuccessHandler myAuthenticationSuccessHandler(){
        logger.info("GOt into the thingie");
        return new MySimpleUrlAuthenticationSuccessHandler();
    }
}

class MySimpleUrlAuthenticationSuccessHandler
    implements AuthenticationSuccessHandler {

    private static final Logger logger = LogManager.getLogger(SecurityConfig.class);

    private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request,
        HttpServletResponse response, 
        Authentication authentication)
        throws IOException {

        handle(request, response, authentication);
        clearAuthenticationAttributes(request);
    }

    protected void handle(HttpServletRequest request,
        HttpServletResponse response, Authentication authentication)
        throws IOException {

        logger.info("got here");
        String targetUrl = determineTargetUrl(authentication);

        if (response.isCommitted()) {
            logger.info(
                "Response has already been committed. Unable to redirect to " + targetUrl);
            return;
        }

        redirectStrategy.sendRedirect(request, response, targetUrl);
    }

    protected String determineTargetUrl(Authentication authentication) {
        logger.info("got here in target");
        boolean isUser = false;
        boolean isAdmin = false;
        Collection<? extends GrantedAuthority> authorities
            = authentication.getAuthorities();
        for (GrantedAuthority grantedAuthority : authorities) {
            if (grantedAuthority.getAuthority().equals("ROLE_USER")) {
            isUser = true;
            break;
            } else if (grantedAuthority.getAuthority().equals("ROLE_ADMIN")) {
                isAdmin = true;
                break;
            }
        }

        if (isUser) {
            return "/homepage.html";
        } else if (isAdmin) {
            return "/console.html";
        } else {
            throw new IllegalStateException();
        }
    }

    protected void clearAuthenticationAttributes(HttpServletRequest request) {
        HttpSession session = request.getSession(false);
        if (session == null) {
            return;
        }
        session.removeAttribute
            (WebAttributes.AUTHENTICATION_EXCEPTION);
    }

    public void setRedirectStrategy(RedirectStrategy redirectStrategy) {
        this.redirectStrategy = redirectStrategy;
    }
    protected RedirectStrategy getRedirectStrategy() {
        return redirectStrategy;
    }
}

控制器如下所示:

@RequestMapping(value = "/", method= RequestMethod.GET)
public String login(Model model){
    return "login";
}

@RequestMapping(value = "/login", method= RequestMethod.GET)
public String loginSucc(Model model){
    return "predictions";
}

在 src/main/resources/templates 下是:

templates html

从上图中可以看出,我在模板下拥有所有必需的 html 页面。 ** Predictions.html 是否也存在,只是未包含在屏幕截图中。 最后 login.html 看起来像这样:

<!-- Login Form -->
<form th:action="@{/login}" method="post">
    <input type="text" id="login" class="fadeIn second" name="login" placeholder="login">
    <input type="text" id="password" class="fadeIn third" name="login" placeholder="password">
    <input type="submit" class="fadeIn fourth" value="Log In">
</form>

在获取登录页面并输入任何用户名和密码后,它会重定向到预测页面。它显然没有进行身份验证,因为没有检查用户名/密码,并且在预测页面中我打印出刚刚没有出现的用户名(空白)。我已根据下面的评论添加了 sn-p。但这并没有什么区别。

从“login.html”重定向后的预测页面: enter image description here

【问题讨论】:

  • POST 时到底发生了什么?
  • 编辑了帖子以显示究竟发生了什么并添加了一张图片。它重定向到预测页面,但它没有通过身份验证,因为它显示登录?错误,但我可以看到预测页面。

标签: java rest spring-boot spring-security thymeleaf


【解决方案1】:

也覆盖此方法 configure(WebSecurity web) 并修改如下代码

 @Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .antMatchers("/user/**").hasRole("USER")
                .anyRequest().authenticated()
                .and()
                .formLogin()
            .loginPage("/login")
            .defaultSuccessUrl("/module",true)
            .failureUrl("/login?error=true")
        .permitAll();// others according to your need
    }
      @Override
        public void configure(WebSecurity web) throws Exception {
            web
                    .ignoring()
                    .antMatchers("/resources/**", "/static/**", "/css/**", "/js/**", "/images/**","/vendor/**","/fonts/**");
        }
}

【讨论】:

  • 只尝试了这段代码,它不起作用。我可以在日志中看到:“.ssUserDetailsS​​erviceAutoConfiguration:使用生成的安全密码:100fc149-c427-4010-8da9-1d278fa12d17”和创建过滤器链:Ant [pattern='/resources/**'], [] [pattern=' /static/**']、[pattern='/css/**']、[]等。但所看到的只是预测页面和显示 localhost:8090/login 的 url,而没有实际触发 login.html 页面
  • 登录成功后实际想去哪里?
  • 我希望它转到templates/predictions.html下的predictions.html。我不希望在 URL 栏中持续显示登录信息,我希望成功登录。我看不到根据上述日志行记录的成功处理程序中的任何内容,当前当它重定向到预测时,URL 栏显示登录错误并且我没有得到登录的用户名(页面应该说 Hello!'User')因为我相信它实际上根本没有登录和验证。不知怎的,它绕过了它
  • 首先,我不明白你为什么使用MySimpleUrlAuthenticationSuccessHandler 类? 2、角色不匹配。你应该首先阅读文档。
【解决方案2】:

问题在于输入类型名称是登录名而不是用户名:

这解决了它:

  <form th:action="@{/login}" method="post">
            <input type="text" id="username" class="fadeIn second" name="username" placeholder="login">
            <input type="text" id="password" class="fadeIn third" name="password" placeholder="password">

【讨论】:

    猜你喜欢
    • 2014-06-14
    • 2019-10-04
    • 2019-09-12
    • 2017-05-14
    • 1970-01-01
    • 2015-06-20
    • 2011-07-03
    • 1970-01-01
    • 2019-08-12
    相关资源
    最近更新 更多