带有 Spring Security 登录和身份验证的 Angular
Posted
技术标签:
【中文标题】带有 Spring Security 登录和身份验证的 Angular【英文标题】:Angular with Spring Security Login and Authentication 【发布时间】:2016-05-30 22:50:18 【问题描述】:我们在前端使用 AngularJS,在后端使用 spring。 Spring security 应该进行身份验证和登录,但它甚至不能在 spring 的教程 (https://spring.io/guides/tutorials/spring-security-and-angular-js/) 的帮助下工作。每次我们尝试登录“用户”服务时,主体对象都是空的。在前端,我们收到了这个答案:data = Object data: "", status: 200, config: Object, statusText: "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>
我们的login.js:
(function(angular)
const app = angular.module("LoginApp",[]);
app.controller("LoginController", ["$scope", "$http", function($scope, $http)
$scope.username = "";
$scope.password = "";
$scope.errormessage = "";
$scope.error = false;
$scope.valid = false;
$scope.requesting = false;
$scope.submitLogin = function()
$scope.requesting = true;
$scope.error = false;
const credentials =
username: $scope.username,
password: $scope.password
;
const headers = credentials ? authorization : "Basic "
+ btoa(credentials.username + ":" + credentials.password)
: ;
$http.get("user", headers: headers ).then(function(data)
if(data.data.name)
window.location.href = "/";
else
$scope.error = true;
$scope.requesting = false;
$scope.errormessage = "Username / Passwort ist falsch!";
,
function(reason)
$scope.error = true;
$scope.requesting = false;
if(reason.status === 404 || reason.status === 408)
$scope.errormessage = "Verbindung zum Server konnte nicht hergestellt werden!";
else if (reason.status === 403)
$scope.errormessage = "Username / Passwort ist falsch!";
else
$scope.errormessage = "Unbekannter Fehler ist bei der Anfrage aufgetreten! Bitte versuchen Sie es erneut";
)
;
$scope.checkValid = function()
if($scope.username != undefined && $scope.username != null && $scope.username.length > 1 &&
$scope.password != undefined && $scope.password != null && $scope.password.length > 1)
$scope.valid = true;
else
$scope.valid = false;
;
]);
)(window.angular);
我们的身份验证服务(如教程或许多帖子中所述):
@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());
最后我们的 Spring Security 配置
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() 而不指定登录表单时,当我尝试访问安全资源时会出现一个浏览器对话框。 我想要重定向到自定义登录页面而不是浏览器对话框。 怎么办?
【问题讨论】:
我认为你应该通过this 来获取spring auth security 感谢您的回答。您认为我的代码到底有什么问题?顺便说一句,当我使用 method="post" 和 action="login" 做一个简单的表单时,它可以使用此身份验证。但是没有角度和这项服务的方式。 实际上你的代码太长了,所以我没有准确地找到你出错的地方,好的,我发布了一些角度的身份验证代码可能会对你有所帮助$http.get("user", headers: headers ).then(function(data) if(data.data.name) ...
这个电话是错误的。
$http 方法是对的,但我认为您忘记在用户之前写/
:$http.get("/user", headers: headers ).then(...
因为url 以/
开头
【参考方案1】:
好的,我通过使用 JSON Web 令牌、自定义无状态过滤器并在每次请求时将令牌返回给前端来获得它。
【讨论】:
我想问一个简单的问题,您使用前端的 Angular 应用程序和后端的 spring-boot 应用程序实现了这一点?您是否需要在前端应用程序中集成 springsecurity 表单登录?【参考方案2】:试试这个:
.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");
);
;
【讨论】:
这个脚本到底是什么,我应该在哪里具体调用“刷新”方法?当我使用默认登录页面时,我的身份验证是正确的。所以这可能是我的 login.html 或我的 javascript 中的问题。 从 angular/javascript 看标题是什么样的? 但我认为您的 js 代码是正确的,并且 Spring Security 存在一些问题,它允许您所有的 antMatchers() 什么样的问题?以上是关于带有 Spring Security 登录和身份验证的 Angular的主要内容,如果未能解决你的问题,请参考以下文章
一个应用程序中的 Spring Security OAuth2 身份验证和表单登录
Spring Security WebFlux - 带有身份验证的主体
Spring Security:添加“伪登录”以更改用户信息
带有表单登录的 Spring Security OAuth 2