我們有選擇理想的方法來處理在分佈式應用程序的認證和權限的問題:如何管理Angular 4應用程序和應用程序之間的身份驗證(Spring Boot/security)?
後端由JAVA EE(春季啓動)開發/ Tomcat服務器的
前端是通過角4 /服務器的NodeJS開發
我們使用Spring安全框架,到目前爲止,我們已經使用了3個可用選項(HTTP Basic中,智威湯遜和OAuth2用戶),同時努力適應一個基因代碼由Jhipster項目評估,但不幸的是,仍然停留在想要認證的用戶信息的恢復中。
換句話說,用戶輸入他的用戶名和密碼,服務器通過URL(http://localhost:8080/api/authenticate)
接收該信息通過在java和客戶端調試,我看到服務器已經恢復(用戶名/密碼),並向瀏覽器發送以下形式的令牌(對於Oauth2):
{「access_token」:「1b0ac85d-b4ed-463f-af3a-acbce7d28353」,「token_type」:「bearer」,「 refresh_token「:」ed2f9041-7726-4939-93ba-4816503e3859「,」expires_in「:1799,」scope「:」讀寫「}
但之後,我必須檢索已經該用戶的信息,將它們存儲在localStorage的(角4),並重新使用它們,這就是爲什麼叫第一web服務後上面引述的,我所說的第二個Web服務: (http://localhost:8080/auth/account)
這時時,鏈接函數來檢索數據庫信息,發送具有用戶名/密碼=空查詢,這給我們一個500消息
在Java應用程序:
/**
* GET /authenticate : check if the user is authenticated, and return its
* login.
*
* @param request
* the HTTP request
* @return the login if the user is authenticated
*/
@RequestMapping(value = ApiConstants.API_ANONYME + "/authenticate", method = RequestMethod.GET)
public String isAuthenticated(HttpServletRequest request) {
log.debug("REST request to check if the current user is authenticated");
String remoteUser = request.getRemoteUser();
return remoteUser;
}
/**
* GET /account : get the current user.
*
* @return the ResponseEntity with status 200 (OK) and the current user in
* body, or status 500 (Internal Server Error) if the user couldn't
* be returned
*/
// @GetMapping("/account")
@RequestMapping(value = ApiConstants.API_AUTH + "/account", method = RequestMethod.GET)
public ResponseEntity<Utilisateur> getAccount() {
Utilisateur userWithAuthorities = userService.getUserWithAuthorities();
return Optional.ofNullable(userWithAuthorities)
.map(user -> new ResponseEntity<>(new Utilisateur(), HttpStatus.OK))
.orElse(new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR));
}
在角4應用:
export class ConnexionBodyComponent implements OnInit {
// model = new Login("", "");
authenticationError: boolean;
password: string;
rememberMe: boolean;
username: string;
credentials: any;
constructor(private loginService: LoginService, private router: Router,
private eventManager: EventManager, private stateStorageService:
StateStorageService) {
}
ngOnInit() {
}
login() {
this.loginService.login({
username: this.username,
password: this.password,
rememberMe: this.rememberMe
}).then(() => {
this.authenticationError = false;
/*if (this.router.url === '/register' ||
(/activate/.test(this.router.url)) ||
this.router.url === '/finishReset' || this.router.url ===
'/requestReset') {
this.router.navigate(['']);
}*/
console.log(this.authenticationError);
this.eventManager.broadcast({
name: 'authenticationSuccess',
content: 'Sending Authentication Success'
});
// // previousState was set in the authExpiredInterceptor before being
redirected to login modal.
// // since login is succesful, go to stored previousState and clear
previousState
const redirect = this.stateStorageService.getUrl();
if (redirect) {
this.router.navigate([redirect]);
}
}).catch(() => {
this.authenticationError = true;
});
}
}
的AccountService:
@Injectable()
export class AccountService {
constructor(private http: Http) { }
get(): Observable<any> {
return
this.http.get(LocalhostSettings.API_ENDPOINT+'/auth/account').map((res:
Response) => res.json());
}
save(account: any): Observable<Response> {
return
this.http.post(LocalhostSettings.API_ENDPOINT+'/auth/account',
account);
}
}
auth.service.ts:
@Injectable()
export class AuthService {
constructor(
private principal: Principal,
private stateStorageService: StateStorageService,
private router: Router
) {}
authorize(force) {
const authReturn = this.principal.identity(force).then(authThen.bind(this));
return authReturn;
function authThen() {
const isAuthenticated = this.principal.isAuthenticated();
const toStateInfo = this.stateStorageService.getDestinationState().destination;
// an authenticated user can't access to login and register pages
if (isAuthenticated && (toStateInfo.name === 'register')) {
this.router.navigate(['']);
return false;
}
// recover and clear previousState after external login redirect (e.g. oauth2)
const fromStateInfo = this.stateStorageService.getDestinationState().from;
const previousState = this.stateStorageService.getPreviousState();
if (isAuthenticated && !fromStateInfo.name && previousState) {
this.stateStorageService.resetPreviousState();
this.router.navigate([previousState.name], { queryParams: previousState.params });
return false;
}
if (toStateInfo.data.authorities && toStateInfo.data.authorities.length > 0) {
return this.principal.hasAnyAuthority(toStateInfo.data.authorities).then((hasAnyAuthority) => {
if (!hasAnyAuthority) {
if (isAuthenticated) {
// user is signed in but not authorized for desired state
this.router.navigate(['accessdenied']);
} else {
// user is not authenticated. Show the state they wanted before you
// send them to the login service, so you can return them when you're done
const toStateParamsInfo = this.stateStorageService.getDestinationState().params;
this.stateStorageService.storePreviousState(toStateInfo.name, toStateParamsInfo);
// now, send them to the signin state so they can log in
this.router.navigate(['accessdenied']).then(() => {
console.log('accessdenied');
});
}
}
return hasAnyAuthority;
});
}
return true;
}
}
}
AUTH-oauth2.service.ts:
@Injectable()
export class AuthServerProvider {
constructor(
private http: Http,
private base64: Base64,
private $localStorage: LocalStorageService
) {}
getToken() {
return this.$localStorage.retrieve('authenticationToken');
}
login(credentials): Observable<any> {
const data = 'username=' + encodeURIComponent(credentials.username) + '&password=' +
encodeURIComponent(credentials.password) + '&grant_type=password&scope=read%20write&' +
'client_secret=my-secret-token-to-change-in-production&client_id=directinfoapp';
const headers = new Headers ({
'Content-Type': 'application/x-www-form-urlencoded',
'Accept': 'application/json',
'Authorization': 'Basic ' + this.base64.encode('directinfoapp' + ':' + 'my-secret-token-to-change-in-production')
});
/*
{"access_token":"ff102054-2072-4c29-91a8-c8f43246a3b7","token_type":"bearer","refresh_token":"94b68064-98a6-49e5-9dbc-0cac34e434f3","expires_in":1799,"scope":"read write"}
*/
console.log("headers : " + headers);
return this.http.post(LocalhostSettings.API_ENDPOINT+'/oauth/token', data, {
headers
}).map(authSuccess.bind(this));
function authSuccess(resp) {
const response = resp.json();
console.log("authSuccess " + resp.json())
const expiredAt = new Date();
expiredAt.setSeconds(expiredAt.getSeconds() + response.expires_in);
response.expires_at = expiredAt.getTime();
this.$localStorage.store('authenticationToken', response);
return response;
}
}
logout(): Observable<any> {
return new Observable(observer => {
this.http.post('api/logout', {});
this.$localStorage.clear('authenticationToken');
observer.complete();
});
}
}
login.service.ts
@Injectable()
export class LoginService {
constructor(
private principal: Principal,
private authServerProvider: AuthServerProvider
) {}
login(credentials, callback?) {
const cb = callback || function() {};
return new Promise((resolve, reject) => {
this.authServerProvider.login(credentials).subscribe((data) => {
this.principal.identity(true).then((account) => {
// After the login the language will be changed to
// the language selected by the user during his registration
if (account !== null) {
account.langKey;
}
resolve(data);
});
return cb();
}, (err) => {
this.logout();
reject(err);
return cb(err);
});
});
}
logout() {
this.authServerProvider.logout().subscribe();
this.principal.authenticate(null);
}
}
principal.service:
@Injectable()
export class Principal {
private userIdentity: any;
private authenticated = false;
private authenticationState = new Subject<any>();
constructor(
private account: AccountService
) {}
authenticate(identity) {
this.userIdentity = identity;
this.authenticated = identity !== null;
this.authenticationState.next(this.userIdentity);
}
hasAnyAuthority(authorities: string[]): Promise<boolean> {
if (!this.authenticated || !this.userIdentity || !this.userIdentity.authorities) {
return Promise.resolve(false);
}
for (let i = 0; i < authorities.length; i++) {
if (this.userIdentity.authorities.indexOf(authorities[i]) !== -1) {
return Promise.resolve(true);
}
}
return Promise.resolve(false);
}
hasAuthority(authority: string): Promise<boolean> {
if (!this.authenticated) {
return Promise.resolve(false);
}
return this.identity().then((id) => {
return Promise.resolve(id.authorities && id.authorities.indexOf(authority) !== -1);
},() => {
return Promise.resolve(false);
});
}
identity(force?: boolean): Promise<any> {
if (force === true) {
this.userIdentity = undefined;
}
// check and see if we have retrieved the userIdentity data from the server.
// if we have, reuse it by immediately resolving
if (this.userIdentity) {
return Promise.resolve(this.userIdentity);
}
// retrieve the userIdentity data from the server, update the identity object, and then resolve.
return this.account.get().toPromise().then((account) => {
if (account) {
this.userIdentity = account;
this.authenticated = true;
} else {
this.userIdentity = null;
this.authenticated = false;
}
this.authenticationState.next(this.userIdentity);
return this.userIdentity;
}).catch((err) => {
this.userIdentity = null;
this.authenticated = false;
this.authenticationState.next(this.userIdentity);
return null;
});
}
isAuthenticated(): boolean {
return this.authenticated;
}
isIdentityResolved(): boolean {
return this.userIdentity !== undefined;
}
getAuthenticationState(): Observable<any> {
return this.authenticationState.asObservable();
}
getImageUrl(): String {
return this.isIdentityResolved() ? this.userIdentity.imageUrl : null;
}
}
任何想法如何,我可以完成這件事?
我恐怕你的問題太長,不太清楚。也許你可以編輯它,並添加一個高層次的概述你想要達到的目標(誰需要OAuth2令牌,你使用的OAuth2流量)以及你嘗試過的。要描述身份驗證過程,您可以使用一系列步驟,其中每個步驟都說明由誰執行的操作以及結果是什麼。 –
我的目標是管理角度4應用程序和彈簧引導應用程序之間的安全部分,如果您有教程或鏈接,我不知道這樣做的理想選擇(Ouath 2,HTTP Basic或JWT)在哪裏我可以找到更多的細節,我會感激你 –