Spring boot 2.3.1 + spring security + angular 7を使用してwebappを実行しようとしています。現在の主な目的は、ユーザーが(カスタムAngularログインページを使用して)ログインしたい場合、フロントエンドがデータ(usernameとパスワード)バックエンドへの認証とフロントエンドへのメッセージの送信を希望します(OKメッセージなど)
私のプロジェクトは次のように機能します。mavenを使用して角度のあるフロントエンドを構築し、「dist」フォルダーからファイル/フォルダーをコピーして、バックエンドのリソースフォルダーに配置します。このソリューションですべてが機能しているので、春のセキュリティ部分を追加します。
SecurityConfig.java
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user1").password("{noop}password123").roles("USER");
}
@Override
protected void configure(final HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
//.antMatchers(HttpMethod.POST, "/auth").permitAll() // I tried this but nothing
.antMatchers(HttpMethod.GET, "/login", "/index*", "/static/**", "/*.js", "/*.json", "/*.ico", "/*.sccs", "/*.woff2", "/*.css").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/")
.loginProcessingUrl("/auth")
.usernameParameter("username")
.passwordParameter("password")
.failureUrl("/index.html?error=true")
.permitAll();
}
}
ApiController.java
@RestController
public class ApiController {
@PostMapping("/auth")
public boolean login(@RequestBody User user) {
return user.getUserName().equals("user") && user.getPassword().equals("password"); // I would like to authenticate with auth.inMemoryAuthentication()
}
}
私は2つの変数(ユーザー名とパスワード)を持つUser.javaを持っています
login.components.ts
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { FormGroup } from '@angular/forms';
import { LoggerService } from '@app/core/services/logger.service';
import { Http } from "@angular/http";
import { FormControlHelper, Globals } from '@app/core/helpers/index';
import { loginValidation } from '@app/models/form-validations/index';
import { HttpParams, HttpHeaders} from "@angular/common/http";
import { URLSearchParams } from "@angular/http"
import { MatSnackBar } from '@angular/material/snack-bar';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
})
export class LoginComponent implements OnInit {
// Properties
globals: Globals;
public loginForm: FormGroup;
public loginValidationModel: any;
public waiting: boolean;
public hidePassword: boolean;
public params = new HttpParams();
constructor(
globals: Globals,
private router: Router,
private logger: LoggerService,
public http : Http,
private snackBar: MatSnackBar
) {
this.loginValidationModel = loginValidation;
this.hidePassword = true;
this.globals = globals;
}
openSnackBar(message: string, action: string) {
this.snackBar.open(message, action, {
duration: 5000,
verticalPosition: 'top', // 'top' | 'bottom'
horizontalPosition: 'center', //'start' | 'center' | 'end' | 'left' | 'right'
panelClass: ['red-snackbar'],
});
}
ngOnInit() {
const formGroupObj = FormControlHelper.generateFormControls(this.loginValidationModel);
if (formGroupObj) {
this.loginForm = new FormGroup(formGroupObj);
} else {
this.logger.error(new Error('Error generating the form modal & validations'));
}
}
public onSubmit() {
let urlSearchParams = new URLSearchParams();
urlSearchParams.append('username', this.loginForm.value.username );
urlSearchParams.append('password', this.loginForm.value.password );
console.log("urlSearchParams: " + urlSearchParams);
this.http.post("auth", urlSearchParams)
.subscribe(
response => {
if(response) { //Here I always get code 200 with "OK" status, even if the username/password is bad, I don't know how to fix this part
this.globals.loggeduser=this.loginForm.value.username;
this.router.navigateByUrl('/somewhere');
} else {
alert("Authentication failed");
}
}
);
}
}
私はこれを理解するためにhttps://spring.io/guides/tutorials/spring-security-and-angular-js/を試しました(いくつかのBaeldungチュートリアルで)が、今は少し混乱しています。誰かが私を助けてくれますか?ありがとう。良い一日を。
編集:.warファイルを作成し、Tomcatを使用しています。
Edit2:詳細といくつかの進展。2つの例を示します。1つの有効なユーザー名/パスワードと1つの無効なユーザー名/パスワードでログインします。ユーザー名/パスワードが無効な場合、URLにこの「?error」の部分が表示されることがわかります。私の問題:エラーにもかかわらず、フロントエンド側でログインでき、すべて(サブページ)にアクセスできます。この問題を解決するにはどうすればよいですか?(ログインが有効な場合->バックエンド/フロントエンドでリダイレクトして認証し、それを保存するため、ログインが無効な場合でもサブページにログインする必要はありません。ログインページに留まるだけで、リダイレクトせず、エラーメッセージが表示されます。 )login.component内の "public onSubmit()"メソッドを作り直す必要があることはわかっていますが、方法がわかりません。注:どちらの応答も「OK」がtrueで、ステータスが200です。
Edit3:もう1つの質問があります。正しい場合、loginProcessingUrlを使用すると、コントローラーでデータを処理できません(/ authにマッピング)。この場合、それは役に立たないでしょう?
可能な解決策を見つけました。
SecurityConfiguration.javaを少し修正しました(succesHandler / failureHandlerを追加しました)
SecurityConfiguration.java
@Override
protected void configure(final HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests()
.antMatchers(HttpMethod.GET, "/login", "/index*", "/static/**", "/*.js", "/*.json", "/*.ico", "/*.sccs","/*.woff2", "/*.css").permitAll()
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/")
.loginProcessingUrl("/auth")
.usernameParameter("username")
.passwordParameter("password")
.successHandler(successHandler())
.failureHandler(failureHandler())
.permitAll()
.and()
.logout().permitAll();
}
private AuthenticationSuccessHandler successHandler() {
return new AuthenticationSuccessHandler() {
@Override
public void onAuthenticationSuccess(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse, Authentication authentication)
throws IOException, ServletException {
httpServletResponse.getWriter().append("OK");
httpServletResponse.setStatus(200);
}
};
}
private AuthenticationFailureHandler failureHandler() {
return new AuthenticationFailureHandler() {
@Override
public void onAuthenticationFailure(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse, AuthenticationException e)
throws IOException, ServletException {
httpServletResponse.getWriter().append("Authentication failure");
httpServletResponse.setStatus(401);
}
};
}
その後、フロントエンドのログインコンポーネントも変更しました。
let urlSearchParams = new URLSearchParams();
urlSearchParams.append('username', this.loginForm.value.username );
urlSearchParams.append('password', this.loginForm.value.password );
if(this.loginForm.value.username != null && this.loginForm.value.password != null) {
this.http.post("auth", urlSearchParams).subscribe(
response => {
if(response.status == 200 && response.ok == true) {
this.globals.loggeduser=this.loginForm.value.username;
this.router.navigateByUrl('/somewhere');
} else {
this.openSnackBar("Wrong username or password!","");
}
}
);
}
そして、これらの変更後、すべてが機能しています。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加