Java 使用Spring安全登录和身份验证

Java 使用Spring安全登录和身份验证,java,angularjs,spring,spring-mvc,spring-security,Java,Angularjs,Spring,Spring Mvc,Spring Security,我们在前端使用AngularJS,在后端使用spring。Spring security将进行身份验证和登录,但在Spring教程()的帮助下,它甚至无法工作。每次我们尝试登录“用户”服务时,主体对象都为null。在前端,我们收到这样的答案:data=Object{data:”,状态:200,配置:Object,状态文本:“OK”}EVERYTIME。使用正确或不正确的数据登录并不重要……我读了很多文章,但找不到解决方案 我们的login.html <!DOCTYPE html> &

我们在前端使用AngularJS,在后端使用spring。Spring security将进行身份验证和登录,但在Spring教程()的帮助下,它甚至无法工作。每次我们尝试登录“用户”服务时,主体对象都为null。在前端,我们收到这样的答案:
data=Object{data:”,状态:200,配置:Object,状态文本:“OK”}
EVERYTIME。使用正确或不正确的数据登录并不重要……我读了很多文章,但找不到解决方案

我们的login.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <title>Login</title>
    <link rel="stylesheet" type="text/css" href="stylesheets/bootstrap.min.css" />
    <script src="scripts/angular.min.js"></script>
    <script src="scripts/login.js"></script>
    <style>
        body {
            position: relative;
        }
    </style>
</head>

<body ng-app="LoginApp">
    <div class="modal show" ng-controller="LoginController">
        <div class="modal-header">
            <h1 class="text-center">Login</h1>
        </div>
        <div class="modal-body">
            <form>
                <div class="control-group">
                    <div class="controls">
                        <input class="input-block-level" type="text" placeholder="Username" ng-model="username" ng-change="checkValid()" ng-disabled="requesting">
                    </div>
                </div>
                <div class="control-group">
                    <div class="controls">
                        <input class="input-block-level" type="password" placeholder="Password" ng-model="password" ng-change="checkValid()" ng-disabled="requesting">
                    </div>
                </div>
                <span class="error" ng-bind="errormessage" ng-show="error"></span>
                <!--
                <div class="control-group">
                    <label class="checkbox">
                        <input type="checkbox">Remember me</label>
                </div>
                -->
            </form>
        </div>
        <div class="modal-footer">
            <!--
            <button class="btn btn-link">Forgot password?</button>
            -->
            <button class="btn btnExtra btn-large btn-primary" ng-click="submitLogin()" ng-disabled="requesting || !valid">Login</button>
        </div>
    </div>
</body>

</html>
我们的认证服务(如教程或许多帖子所述):

@RestController
public class UserController {
    @RequestMapping(value = "/user")
    public Principal user(Principal user) {
        return user;
    }
}
SecurityWebAppInitializer带有一个自定义过滤器,该过滤器应记录IP和用户名

@Order(2)
public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {
    @Override
    protected void afterSpringSecurityFilterChain(ServletContext servletContext) {
        super.beforeSpringSecurityFilterChain(servletContext);
        insertFilters(servletContext,new MultipartFilter(),new MDCFilter());
    }
}
最后,我们的春季安全配置

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.csrf.CsrfFilter;
import org.springframework.security.web.csrf.CsrfTokenRepository;
import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository;

@Configuration
@EnableWebSecurity(debug=true)
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    DataSource dataSource;

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth
        .jdbcAuthentication()
             .dataSource(dataSource)
                .usersByUsernameQuery(
                        "select email,pwHash,true from user where email = ?")
                .authoritiesByUsernameQuery(
                        "select email, rolle_rollenname from user where email = ?");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
    http
            .authorizeRequests()
            .antMatchers("/user", "/login", "/logout", "login.html").permitAll()
            .anyRequest().authenticated()
        .and()
            .csrf().csrfTokenRepository(csrfTokenRepository())
        .and()
            .addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class)
        .formLogin()
            .loginPage("/login")
            //.logoutSuccessHandler(new customLogoutSuccessHandler())
            .and()
        .logout()
            .logoutUrl("/logout");
    }
    @Override
    public void configure(WebSecurity web) throws Exception {
         web
            .ignoring()
            .antMatchers("/scripts/**")
            .antMatchers("/stylesheets/**");
    }

    private CsrfTokenRepository csrfTokenRepository() 
    { 
        HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
        repository.setHeaderName("X-XSRF-TOKEN");
        return repository; 
    }
}
使用自定义身份验证和默认登录页面时,它可以正常工作可能login.html或login.js错误

更新

当我使用.httpBasic()而不指定loginform时,当我尝试访问受保护的资源时,会出现一个浏览器对话框。 我希望重定向到自定义登录页,而不是浏览器对话框怎么办?

试试这个:

.factory('AuthFactory', ['$http', 'contextPath', '$q', '$timeout', function ($http, contextPath, $q, $timeout) {

            function User() {
            };

            var currentUser = null;

            var userChangeCallbacks = [];

            var notifyUserChange = function (newUser) {
                angular.forEach(userChangeCallbacks, function (callback) {
                    $timeout(function () {
                        callback(newUser);
                    });
                });
            };

            var exported = {
                getCurrentUser: function () {
                    return currentUser;
                },
                refresh: function () {
                    return $q(function (resolve, reject) {
                        //Get the current user
                        $http.get(contextPath + '/rest/user/current')
                                .success(function (data) {
                                    currentUser = new User();
                                    for (var key in data) {
                                        currentUser[key] = data[key];
                                    }
                                    notifyUserChange(currentUser);
                                    resolve(currentUser);
                                })
                    });
                },
                registerUserChangeHandler: function (callback) {
                    console.log("registered handler: " + callback);
                    userChangeCallbacks.push(callback);
                }
            };

            return exported;
        }]);
然后在登录控制器中调用该刷新方法

登录控制器

$scope.login = function (username, password) {
            UserService.login({
                'username': username,
                'password': password
            }, function () {
                AuthFactory.refresh();
                $state.go("home");
            });
        };

好的,我是通过使用JSON Web令牌(一种自定义无状态过滤器)获得的,每次当他们要求某项服务时,我都会将令牌返回到前端。

我想你应该通过spring auth Security来验证。谢谢你的回答。你认为我的代码有什么错误?顺便说一句,当我使用method=“post”和action=“login”创建一个简单表单时,它与此身份验证一起工作。但是angular和这个服务没有。事实上你的代码太长了,所以我不能准确地理解你的错误,好的,我在angular中发布一些身份验证代码,可能会帮助你
$http.get(“用户”,{headers:headers})。然后(函数(数据){if(data.data.name){…
这个调用是错误的。$http方法是正确的,但我认为您忘记在user:
$http.get(“/user”,“headers:headers}”)之前编写
/
。然后(…
因为url以
/
开头,这个脚本到底做了什么,我应该在哪里具体地调用“refresh”方法?当我使用默认登录页面时,我的AuthenticationIn是正确的。因此,这可能是我的login.html或javascript中的一个问题。从angular/javascript看,标题是什么样子的?但我认为您的js代码是正确的,而且spring安全性中存在一些问题,它允许所有antMatchers()什么样的问题?我想问一个简单的问题,你是通过前端的angular应用程序和后端的spring boot应用程序实现的?你不需要在前端应用程序中集成springsecurity表单登录吗?
$scope.login = function (username, password) {
            UserService.login({
                'username': username,
                'password': password
            }, function () {
                AuthFactory.refresh();
                $state.go("home");
            });
        };