Как создать систему аутентификации с помощью Spring Security? - PullRequest
1 голос
/ 04 июня 2019

Я прочитал документацию 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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...