mysql - Angular , Spring 安全 MYSQL 基本登录
问题描述
我尝试制作一个简单的登录和注册页面。Fronted 是由 Angular 制作的 Spring 框架中的后端。用户数据保存在 MYSQL DB 中。我的问题是我不知道如何在后端使用数据库检查我的凭据。成功登录后,我想重定向到/欢迎页面和不成功的打印错误消息。另外,我不知道登录端点是否正确。以角度或/登录形式调用/ basicauth?
我还有一个注册页面,可以在数据库中工作并存储新用户。
我的错误控制台.log
从源“ http://localhost:4200 ”访问“ http://localhost:8080/basicauth ”处的 XMLHttpRequest已被 CORS 策略阻止:对预检请求的响应未通过访问控制检查:不允许重定向预检请求。login.component.ts:33 HttpErrorResponse {headers: HttpHeaders, status: 0, statusText: "Unknown Error", url: " http://localhost:8080/basicauth ", ok: false, ...} zone-evergreen.js: 2952 获取http://localhost:8080/basicauth net::ERR_FAILED
用户.java
@Entity
@Table(name = "user")
public class User{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
@Column(name="name")
private String name;
@Column(name="password")
private String password;
@Column(name="role")
private String role;
@Column(name="status")
private boolean status;
public User() {
}
public User(String name, String password) {
this.name = name;
this.password = password;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
public boolean getStatus() {
return status;
}
public void setStatus(boolean status) {
this.status = status;
}
}
用户控制器
@CrossOrigin(origins="http://localhost:4200")
@RestController
public class UserController {
@Autowired
private UserService userService;
@GetMapping(path="/basicauth")
public AuthenticationBean helloWorldBean(){
//throw new RuntimeException("Some Error");
return new AuthenticationBean("You are authenticated");
}
@PostMapping("/registration")
public User create(@RequestBody Map<String, String> body){
String username = body.get("username");
String password = body.get("password");
return userService.saveUser(new User(username, password));
}
}
MyUserDetailsService
@Service
public class MyUserDetailsService implements UserDetailsService {
@Autowired
private UserService userService;
@Override
@Transactional
public UserDetails loadUserByUsername(String userName) {
User user = userService.findUserByName(userName);
List<GrantedAuthority> authorities = getUserAuthority(user.getRole());
return buildUserForAuthentication(user, authorities);
}
private List<GrantedAuthority> getUserAuthority(String userRoles) {
Set<GrantedAuthority> roles = new HashSet<>();
roles.add(new SimpleGrantedAuthority(userRoles));
return new ArrayList<>(roles);
}
private UserDetails buildUserForAuthentication(User user, List<GrantedAuthority> authorities) {
return new org.springframework.security.core.userdetails.User(user.getName(), user.getPassword(),
user.getStatus(), true, true, true, authorities);
}
}
用户服务
@Service
public class UserService {
private UserRepository userRepository;
private BCryptPasswordEncoder bCryptPasswordEncoder;
@Autowired
public UserService(UserRepository userRepository,
BCryptPasswordEncoder bCryptPasswordEncoder) {
this.userRepository = userRepository;
this.bCryptPasswordEncoder = bCryptPasswordEncoder;
}
public User findUserByName(String userName) {
return userRepository.findByName(userName);
}
public User saveUser(User user) {
user.setPassword(bCryptPasswordEncoder.encode(user.getPassword()));
user.setName(user.getName());
user.setStatus(true);
user.setRole("USER");
return userRepository.save(user);
}
}
网络配置
@Configuration
@EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
@Autowired
private MyUserDetailsService userDetailsService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(userDetailsService)
.passwordEncoder(bCryptPasswordEncoder);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
String loginPage = "/login";
String logoutPage = "/logout";
http.
authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers(loginPage).permitAll()
.antMatchers("/registration").permitAll()
.antMatchers("/admin/**").hasAuthority("ADMIN")
.anyRequest()
.authenticated()
.and().csrf().disable()
.formLogin()
.loginPage(loginPage)
.loginPage("/")
.failureUrl("/login?error=true")
.defaultSuccessUrl("/welcome")
.usernameParameter("username")
.passwordParameter("password")
.and().logout()
.logoutRequestMatcher(new AntPathRequestMatcher(logoutPage))
.logoutSuccessUrl(loginPage).and().exceptionHandling();
}
@Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/resources/**", "/static/**", "/css/**", "/js/**", "/images/**");
}
}
HttpIntercepterBasicAuthService.ts
export class HttpIntercepterBasicAuthService {
constructor(
private basicAuthenticationService: BasicAuthenticationService
) { }
intercept(request: HttpRequest<any>, next: HttpHandler){
const basicAuthHeaderString = this.basicAuthenticationService.getAuthenticatedToken();
const username = this.basicAuthenticationService.getAuthenticatedUser()
if (basicAuthHeaderString && username) {
request = request.clone({
setHeaders : {
Authorization : basicAuthHeaderString
}
});
}
return next.handle(request);
}
}
BasicAuthenticationService.ts
export const TOKEN = 'token';
export const AUTHENTICATEDUSER = 'authenticaterUser';
@Injectable({
providedIn: 'root'
})
export class BasicAuthenticationService {
constructor(private http: HttpClient) { }
executeAuthenticationService(username, password) {
const basicAuthHeaderString = 'Basic ' + window.btoa(username + ':' + password);
const headers = new HttpHeaders(
{Authorization: basicAuthHeaderString}
)
return this.http.get<AuthenticationBean>(`${API_URL}/basicauth`,
{headers}).pipe(
map(data => {
sessionStorage.setItem(AUTHENTICATEDUSER, username);
sessionStorage.setItem(TOKEN, basicAuthHeaderString);
return data;
})
);
}
getAuthenticatedUser() {
return sessionStorage.getItem(AUTHENTICATEDUSER);
}
getAuthenticatedToken() {
if (this.getAuthenticatedUser()) {
return sessionStorage.getItem(TOKEN);
}
}
logout() {
sessionStorage.removeItem(AUTHENTICATEDUSER);
sessionStorage.removeItem(TOKEN);
}
isLoggedIn() {
const user = sessionStorage.getItem(AUTHENTICATEDUSER);
return !(user === null);
}
}
export class AuthenticationBean{
constructor(public message: string) { }
}
登录组件.ts
export class LoginComponent implements OnInit {
username = '';
password = '';
errorMessage = 'Špatné přihlašovací údaje';
invalidLogin = false;
// router
constructor(private router: Router,
private basicAuthenticationService: BasicAuthenticationService) { }
ngOnInit() {
}
handleLogin() {
this.basicAuthenticationService.executeAuthenticationService(this.username, this.password)
.subscribe(
data => {
console.log(data);
this.router.navigate(['welcome']);
this.invalidLogin = false;
},
error => {
console.log(error);
this.invalidLogin = true;
}
);
// redirect welcome page
}
}
解决方案
您在将请求从 Angular 应用程序重定向到后端服务器时遇到问题,因为您的前端应用程序尝试从不同的域访问后端。要解决此问题,请使用角度代理:https ://github.com/angular/angular-cli/blob/master/docs/documentation/stories/proxy.md
推荐阅读
- python - 在哈希表 Django 中传递密码
- php - 意外的 Safari 页面加载计数行为
- php - PHP/CSS 如何实现棋盘格样式
- c++ - Clang++ 已更新,尽管它们位于包含目录中,但仍找不到某些标头
- vue.js - 纱线 monorepo 中的 rollup preserveModules 输出完整的项目路径
- javascript - 将变量从视图传递到控制器ajax
- arrays - HIVEQL 中的 indexOf 相似函数
- php - 使用 WooCommerce 插件的折扣规则时,产品 get_sale_price 始终为 0
- reactjs - React - 测试单独的父组件(没有 redux)
- reactjs - 如何将 Map 作为参数从一个 .tsx 文件传递到另一个 .tsx 文件?