【问题标题】:Springboot authentication issueSpring Boot 身份验证问题
【发布时间】:2019-02-13 22:46:46
【问题描述】:

我有一个配置了 spring 安全性的 spring boot 应用程序。我已将登录请求重定向到http://localhost:8000,我在 python 服务器上运行我的前端。现在,当我尝试将登录信息发布到我的 springboot 应用程序时,它不起作用。即使我从邮递员那里尝试,它也会显示405 错误。我怎样才能得到这个工作。如果我将它作为 html 放在同一个项目中而不是从 python 服务器或邮递员中,它可以从 /login 中工作。有什么区别。

"message": "不支持请求方法'POST'", “路径”:“/登录”

表单数据

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>

    <title>Demo</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />


</head>
<body>


<!-- Add page specific code/html START -->

<div class="container">
    <h1 th:text="#{welcome.message}"></h1>

    <form class="form-signin" name="loginForm" th:action="@{/login}" action="/login" method="POST">
        <h2 class="form-signin-heading">Please sign in</h2>
        <label for="username" class="sr-only">Email address</label>
        <input type="text" name="username" id="username" class="form-control" placeholder="Username" required="required" autofocus="autofocus" />
        <label for="password" class="sr-only">Password</label>
        <input type="password" name="password" id="password" class="form-control" placeholder="Password" required="required" />

        <button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
    </form>

</div> <!-- /container -->


</body>
</html>

光子服务器上托管的 HTML 代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Assessment App</title>

    <link href="../css/bootstrap.min.css" rel="stylesheet">
    <link href="../css/main.css" rel="stylesheet">

</head>
<body>

    <div class="container-fluid">
        <div class="panel panel-default main-header">
            <div class="panel-body">
                <div class ="pull-left">Assessments</div>
            </div>
        </div>
        <div class="row">
            <div class="login-container col-md-4 col-md-offset-4 col-sm-10 col-sm-offset-1 col-xs-12 col-xs-offset-0">
                <div class="panel panel-login">
                    <div class="panel-heading">
                        <div class="panel-title">Sign In</div>
                    </div>

                    <div class="panel-body">
                        <form id="loginform" class="form-horizontal" role="form">

                            <div class="input-group assessment-input-group">
                                <span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span>
                                <input id="login-username" type="text" class="form-control" name="username" value="" placeholder="Username">
                            </div>

                            <div class="input-group assessment-input-group">
                                <span class="input-group-addon"><i class="glyphicon glyphicon-lock"></i></span>
                                <input id="login-password" type="password" class="form-control" name="password" placeholder="Password">
                            </div>

                            <div class="form-group">
                                <div class="col-sm-12 controls">
                                    <input class="btn btn-primary" type="submit" value="Login">
                                </div>
                            </div>
                        </form>
                        <div class="login-form-error-text hidden">Invalid credentials</div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <script src="../javascript/jquery-3.3.1.min.js"></script>
    <script src ="../javascript/bootstrap.min.js"></script>
    <script src="../javascript/lodash.min.js"></script>
    <script src="../javascript/login.js"></script>
</body>
</html>

对应的js

$(document).ready(function () {


    $('#loginform').submit(function (event) {
        event.preventDefault();       
        $.ajax({
            url : 'http://localhost:8080/j_spring_security_check',
            type : 'POST',
            contentType : 'application/json',
            data : JSON.stringify({ j_username :  $('#login-username').val(), j_password : $('#login-password').val() }),
            success : function () {
                window.location.href = '../html/assessment.html';
            },  
            error : function () {
                event.preventDefault();
                alert('failed');
            }
        });
    });

    $('.form-tab-header').on('click', function () {
        $('.login-form-error-text').addClass('hidden');
        $('.form-tab-header').removeClass('active');
        $(this).addClass('active');
        $('.form-horizontal').addClass('hidden');
        $('.' + $(this).attr('id') + '-content').removeClass('hidden');
    });
});

安全配置

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Value("${ldap.urls}")
    private String ldapUrls;

    @Value("${ldap.base.dn}")
    private String ldapBaseDn;

    @Value("${ldap.user.dn.pattern}")
    private String ldapUserDnPattern;

    @Value("${ldap.enabled}")
    private String ldapEnabled;


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .authorizeRequests()
                .antMatchers("/login**").permitAll()
                .antMatchers("/assessments/**").fullyAuthenticated()
                .antMatchers("/").permitAll()
                .and()
                .formLogin()
                //.loginPage("http://htmlcode.s3-website.us-east-2.amazonaws.com")
                .loginPage("http://localhost:8000")
                .loginProcessingUrl("/j_spring_security_check")
                .usernameParameter("j_username")
                .passwordParameter("j_password")
                //.loginPage("/login")
                .failureUrl("/login?error")
                .permitAll()
                .and()
                .logout()
                .invalidateHttpSession(true)
                .deleteCookies("JSESSIONID")
                .permitAll();

    }



    @Override
    public void configure(WebSecurity web) {
        web.ignoring().antMatchers("/register");
        // .antMatchers("/assessments/**");
    }


    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        if(Boolean.parseBoolean(ldapEnabled)) {
            auth.ldapAuthentication()
                    .userDetailsContextMapper(userDetailsContextMapper())
                    .userDnPatterns(ldapUserDnPattern)
                    .contextSource()
                    .url(ldapUrls+ldapBaseDn);
        }
    }

    @Bean
    public UserDetailsContextMapper userDetailsContextMapper() {
        return new LdapUserDetailsMapper() {
            @Override
            public UserDetails mapUserFromContext(DirContextOperations ctx, String username, Collection<? extends GrantedAuthority> authorities) {
                UserDetails details = super.mapUserFromContext(ctx, username, authorities);
                return details;
            }
        };
    }

    @Bean
    CorsFilter corsFilter() {
        CorsFilter filter = new CorsFilter();
        return filter;
    }
}

【问题讨论】:

    标签: spring-boot spring-security


    【解决方案1】:

    您忘记包含 csrf 值。这是一种防止跨站点攻击的安全预防机制。您有两种解决方法:

    1.禁用CSRF:

    由于默认情况下启用了 csrf,因此在启用 CSRF 的情况下不允许使用 POST 和 PUT Http 方法。 要禁用它,您应该将其添加到您的安全配置中

    .csrf().disable()
    

    例如你可以有这样的东西:

    http.
    .csrf().disable().
    authorizeRequests()
            .antMatchers("/admin/**").access("hasRole('ROLE_ADMIN')")
            .and()
              .formLogin().loginPage("/login").failureUrl("/login?error")
              .usernameParameter("username").passwordParameter("password")
            .and()
              .logout().logoutSuccessUrl("/login?logout")
            .and()
              .exceptionHandling().accessDeniedPage("/403");
    

    2.发送csrf令牌值:

    如果您使用带有登录表单的登录页面,我们需要始终将登录表单中的 CSRF 令牌作为隐藏参数手动包含在代码中:

    <input
      type="hidden"
      th:name="${_csrf.parameterName}"
      th:value="${_csrf.token}" />
    

    如果你想通过ajax登录你还应该包括这两个参数:

    首先保存一些变量中的值:

    <script type="text/javascript">
        var csrfParameter = '${_csrf.parameterName}';
        var csrfToken = '${_csrf.token}';
    </script>
    

    然后将它们包含在

    var jsonParams = {};
    jsonParams['parentId'] = 1;
    jsonParams[csrfParameter] = csrfToken;
    // include other values pass ,user, etc.
    
    $.ajax({
        type: 'POST',
        cache: false,
        url: /login,
        data: jsonParams,
        dataType = 'json',
        contentType = 'application/json',
    
        ...
    });
    

    更多信息

    【讨论】:

    • 我已经禁用了 csrf。我们是否仍应包含步骤 2 中提到的 csrftoken?
    • 能否请您提供您的安全配置代码,以便我更好地指导您?
    • 编辑了我的问题。请检查
    • 请检查您的浏览器是否禁用了cookies,如果是,请启用并重新检查
    • 你的意思是 405 错误消失了?我看不到你的 successHandler(authenticationsuccessHandler) 吗?您需要在某个地方定义用户是否经过身份验证
    猜你喜欢
    • 2019-04-25
    • 1970-01-01
    • 2019-02-14
    • 2018-02-27
    • 2017-04-12
    • 2019-04-08
    • 1970-01-01
    • 2020-07-02
    • 1970-01-01
    相关资源
    最近更新 更多