Я прочитал документацию Spring Security, чтобы узнать, как создать базовую систему аутентификации для моего веб-приложения, но я не понимаю, какую архитектуру выбрать.
Ссылка: https://docs.spring.io/spring-security/site/docs/5.1.5.RELEASE/reference/htmlsingle/#preface
В настоящее время я использую класс WebSecurityConfigurerAdapter с этим кодом:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/css/**", "/index", "/user/**").permitAll()
//.antMatchers("/user/**").hasRole("USER")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login").failureUrl("/login-error")
.and()
.logout()
.permitAll();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password(passwordEncoder().encode("password")).roles("USER");
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
Но в документации они рекомендуют 3 альтернативных решения.
1) WebMvcConfigurer:
https://docs.spring.io/spring-security/site/docs/5.1.5.RELEASE/reference/htmlsingle/#hello-web-security-java-configuration
2) AuthenticationManager:
https://docs.spring.io/spring-security/site/docs/5.1.5.RELEASE/reference/htmlsingle/#tech-intro-authentication
3) С другими классами, предназначенными для веб-приложений (?)
https://docs.spring.io/spring-security/site/docs/5.1.5.RELEASE/reference/htmlsingle/#tech-intro-web-authentication
Итак, в моей голове сейчас большой беспорядок, и я совсем не знаю, как создать свою систему аутентификации.
Какую архитектуру я должен выбрать?
Вот мои другие занятия в дополнение к пониманию моего проекта:
UserService
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import app.shellx.dao.AuthorityRepository;
import app.shellx.dao.RoleRepository;
import app.shellx.dao.UserRepository;
import app.shellx.model.Authority;
import app.shellx.model.Role;
import app.shellx.model.User;
@Service
public class UserService implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Autowired
private RoleService roleService;
@Transactional(readOnly=true)
public User loadUserByUsername(final String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username);
//List<GrantedAuthority> authorities = buildUserAuthority(user.getAuthorities());
//if you're implementing UserDetails you wouldn't need to call this method and instead return the User as it is
//return buildUserForAuthentication(user, authorities);
return user;
}
/*public User login() {
try {
Authentication request = new UsernamePasswordAuthenticationToken(name, password);
Authentication result = am.authenticate(request);
SecurityContextHolder.getContext().setAuthentication(result);
break;
} catch(AuthenticationException e) {
System.out.println("Authentication failed: " + e.getMessage());
}
}
System.out.println("Successfully authenticated. Security context contains: " +
SecurityContextHolder.getContext().getAuthentication());
}
}*/
/* // Converts user to spring.springframework.security.core.userdetails.User
private User buildUserForAuthentication(User user, List<GrantedAuthority> authorities) {
return new User(user.getUsername(), user.getEmail(), user.getPassword(), authorities, user.isAccountNonExpired(), user.getAvatar());
}
private List<GrantedAuthority> buildUserAuthority(Set<Authority> userRoles) {
Set<GrantedAuthority> setAuths = new HashSet<GrantedAuthority>();
// add user's authorities
for (Authority userRole : userRoles) {
setAuths.add(new SimpleGrantedAuthority(userRole.getRole()));
}
List<GrantedAuthority> Result = new ArrayList()<GrantedAuthority>(setAuths);
return Result;
}*/
public void add(User user, String role) {
user.setRole(roleService.findByRole(role));
this.userRepository.save(user);
/*role.setAuthorities(authorities);
this.roleRepository.save(role);
for (Authority auth : authorities) {
auth.setRoles(role);
this.authorityRepository.save(auth);
}*/
}
public void update(User user) {
this.userRepository.save(user);
}
public String getCurrentUser() {
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String username;
if (principal instanceof UserDetails) {
username = ((User)principal).getUsername();
} else {
username = principal.toString();
}
return username;
}
}
Пользователь
import java.time.LocalDate;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinTable;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
@Entity
@Table(name="users")
public class User implements UserDetails {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name = "id")
private long id;
@Column(name = "users_username", nullable = false, unique = true)
private String username;
@Column(name = "users_email", nullable = false, unique = true)
private String email;
@Column(name = "users_password")
private String password;
@Column(name = "users_enabled")
private boolean enabled;
@Column(name = "users_avatar")
private String avatar;
@Column(name = "users_date")
private LocalDate date;
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
//@JoinTable(name = "authorities", joinColumns = @JoinColumn(name = "users_username"), inverseJoinColumns = @JoinColumn(name = "roles_username"))
private Role role;
public User() {
}
public User(String username, String email, String password, boolean enabled, String avatar) {
this.username = username;
this.email = email;
this.password = password;
this.enabled = enabled;
this.avatar = avatar;
}
public User(String username, String email, String password, Role role, boolean enabled, String avatar) {
this.username = username;
this.email = email;
this.password = password;
this.role = role;
this.enabled = enabled;
this.avatar = avatar;
}
public Collection<? extends GrantedAuthority> getAuthorities() {
Set<Authority> authorities = new HashSet<Authority>();
authorities = role.getAuthorities();
return authorities;
}
public void setName(String username) {
this.username = username;
}
public String getUsername() {
return username;
}
public boolean isEnabled() {
return enabled;
}
public boolean isAccountNonExpired() {
return false;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public boolean isAccountNonLocked() {
// TODO Auto-generated method stub
return false;
}
public boolean isCredentialsNonExpired() {
// TODO Auto-generated method stub
return false;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getAvatar() {
return avatar;
}
public void setAvatar(String avatar) {
this.avatar = avatar;
}
public Role getRole() {
return role;
}
public void setRole(Role role) {
this.role = role;
}
public String getRoleRole() {
return role.getRole();
}
}
РЕДАКТИРОВАТЬ: я использую SPRING BOOT и Hibernate