AngularJS + Spring安全性记住了我的功能

时间:2017-03-19 13:32:05

标签: angularjs spring spring-security

我正在做一个基于spring boot + Angularjs构建的应用程序 我根据此博文发表的身份验证:https://spring.io/guides/tutorials/spring-security-and-angular-js/ 所以我获得了基本的用户名/密码或启用了OAuth2

我想在其中添加Remmeber me功能。我有AuthService

AuthService.authenticate = function (credentials, callback) {
    var headers = credentials ? {
        authorization: "Basic "
        + btoa(credentials.username + ":" + credentials.password)
    } : {};

    $http.get('api/user/', {headers: headers}, {timeout: 5000}).then(
        function (response) {
            var data = response.data;
            if (data.id) {
                $rootScope.authenticated = true;
                $rootScope.principal = data;
                $translate.use($rootScope.principal.language);
                $location.search('lang', $rootScope.principal.language);
                AvatarService.getUserAvatar($rootScope.principal);
                $log.debug("[DEBUG] User logged in " + $rootScope.principal.id);
            } else {
                $rootScope.authenticated = false;
            }
            callback && callback();
        },
        function () {
            $rootScope.authenticated = false;
            callback && callback();
        });
};

在登录控制器中,我得到了处理:

$scope.credentials = {};
//LOGIN
$scope.login = function () {
    AuthService.authenticate($scope.credentials, function () {
        if ($rootScope.authenticated) {
            $location.path("/");
            AlertService.clearAlerts();
        } else {
            $location.path("/login");
            AlertService.addError('user.login.failed');
        }
    });
};

在Spring安全性上,我设置它通常是我设置它,(配置的一部分)

            ....
            .and().formLogin()
                .loginPage("/#/login")
                .and().rememberMe()
                .rememberMeServices(rememberMeServices())
                .key("remember-me-key")
            .and().addFilterBefore(new CsrfHeaderFilter(), CsrfFilter.class)
                .csrf()
            ....

但是我的猜测是期待使用remember-me和而不是基本的auth

如何调整以便能够记住我? 我可以通过post执行调用以使用j_username j_password登录并记住我吗?

3 个答案:

答案 0 :(得分:1)

您可以配置spring boot服务器以将auth令牌发回客户端。在客户端(Angular)中,将令牌保存在某处(本地存储/ cookie)。然后,您可以在应用首次加载时检查令牌是否存在。 在处理Web客户端身份验证时,JWT令牌非常好。

例如,如果我的安全配置文件中有这段代码。

.authorizeRequests()
    .antMatchers("/", "/index.html", "/login.html", "/home.html").permitAll()
.anyRequest()
.authenticated().and()
.formLogin()
    .successHandler(authenticationSuccessHandler)
    .failureHandler(authenticationFailureHandler)

我可以轻松实现authenticationSuccessHandler并在成功登录后向用户发出身份验证令牌或身份验证Cookie,或两者都发回。

public class AuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {

... bla bla bla

@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
        Authentication authentication ) throws IOException, ServletException {
    clearAuthenticationAttributes(request);
    User user = (User)authentication.getPrincipal();

    String jws = tokenHelper.generateToken( user.getUsername() );

    // cookie in response
    Cookie authCookie = new Cookie( TOKEN_COOKIE, ( jws ) );
    authCookie.setPath( "/" );
    authCookie.setHttpOnly( true );
    authCookie.setMaxAge( EXPIRES_IN );
    response.addCookie( authCookie );
    // token in response
    UserTokenState userTokenState = new UserTokenState(jws, EXPIRES_IN);
    String jwtResponse = objectMapper.writeValueAsString( userTokenState );
    response.setContentType("application/json");
    response.getWriter().write( jwtResponse );
}

}

更多细节可在springboot-jwt-starter中找到。这是一个使用spring boot和AngularJS的入门套件项目。

如果您想使用Angular实现Spring启动安全性,The Login Page: Angular JS and Spring Security Part II系列是一个非常好的阅读材料。

答案 1 :(得分:0)

我还在开发Spring + Angular2应用程序。在我的例子中,后端返回2个令牌(访问令牌和刷新令牌)。之后我添加了授权'每个请求的标题:' Bearer' + this.accessToken。

答案 2 :(得分:0)

您可以使用带有Angular和基本身份验证的Spring remember-me服务,您必须使用post发送remember-me参数。

以下是Angular2的示例:

import {Injectable} from "@angular/core";
import {HttpClient, HttpHeaders, HttpParams} from "@angular/common/http";

import {Observable} from "rxjs/Observable";
import {CSRF_URL, LOGIN_URL, LOGOUT_URL} from "./auth.constant";

export interface RespAccess {
  email?: String;
  name: string;
  permissions: [string];
}

@Injectable()
export class AuthenticationService {

  constructor(private http: HttpClient) {}

  login(username: string, password: string, rememberme: boolean): Observable<RespAccess> {
    let headers = new HttpHeaders();
    headers = headers.append('Authorization', 'Basic ' + btoa(username + ':' + password));
    headers = headers.append('X-Requested-With', 'XMLHttpRequest'); // to suppress 401 browser popup

    const params = new HttpParams().append('remember-me', (rememberme ? 'true' : 'false' ));
    return this.http.post<RespAccess>(LOGIN_URL,'', {headers, params});
  }

  logout() : Observable<any> {
    return this.http.post<any>(LOGOUT_URL, '');
  }

  getCSRFToken() {
    this.http.get<any>(CSRF_URL) // /api/auth/csrf
      .subscribe();
  }
}

如果您使用CSRF保护,则必须在登录前获取CSRF令牌。你可以这样做只是访问一个返回令牌的不安全的URL,这是Spring服务器端控制器中的方法:

@RequestMapping("/api/auth/csrf")
public CsrfToken csrf(CsrfToken token) {
    return token;
}