spring authorization server 1.0.1与阿里nacos2.2.2微服务学习笔记(五)

spring security的配置类:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.logout.HeaderWriterLogoutHandler;
import org.springframework.security.web.header.writers.ClearSiteDataHeaderWriter;

import static org.springframework.security.web.header.writers.ClearSiteDataHeaderWriter.Directive.COOKIES;

@EnableWebSecurity
@Configuration(proxyBeanMethods = false)
public class SecurityConfiguration {
    @Bean
    SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
        http
                .authorizeHttpRequests(authorize ->
                        {
                            try {
                                authorize//匿名访问路径
                                        .requestMatchers("/oauth2/anonymous/**")
                                        .permitAll()
                                        .anyRequest().authenticated().and()
                                        .oauth2ResourceServer()
                                        .jwt();
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                )
                .formLogin().loginPage("/login").permitAll()
                .and().logout(logout -> logout.addLogoutHandler(new HeaderWriterLogoutHandler(new ClearSiteDataHeaderWriter(COOKIES))));

        http.csrf().disable();
        http.headers().frameOptions().disable();

        return http.build();
    }

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
}

自定义用户类、角色类:user、role


import com.example.oauth2.role.entity.Role;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import java.time.LocalDateTime;
import java.util.Set;

@Entity
@EntityListeners(AuditingEntityListener.class)
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    private String name;
    private String mobile;
    private String password;

    private Boolean disabled;
    private Boolean locked;

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @Column(nullable = false, updatable = false)
    @CreatedDate
    private LocalDateTime createTime;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @LastModifiedDate
    private LocalDateTime updateTime;

    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(name = "user_role",
            joinColumns = @JoinColumn(name = "userId"),
            inverseJoinColumns = @JoinColumn(name = "roleId")
    )
    @JsonIgnore
    private Set<Role> roles;
}

import com.example.oauth2.user.entity.User;
import com.fasterxml.jackson.annotation.JsonFormat;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import java.time.LocalDateTime;
import java.util.Set;

@Entity
@EntityListeners(AuditingEntityListener.class)
@AllArgsConstructor
@NoArgsConstructor
@Setter
@Getter
public class Role {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    private String name;
    private Boolean disabled;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @Column(nullable = false, updatable = false)
    @CreatedDate
    private LocalDateTime createTime;

    @ManyToMany(mappedBy = "roles")
    private Set<User> users;
}
import com.example.oauth2.user.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Optional;

public interface UserRepository extends JpaRepository<User, Integer> {
    Optional<User> findByMobile(String mobile);
}

import com.example.oauth2.exception.UserExistedException;
import com.example.oauth2.exception.UserNotFoundException;
import com.example.oauth2.user.entity.User;
import com.example.oauth2.user.repository.UserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.List;
import java.util.Optional;

@Service
@RequiredArgsConstructor
public class UserService {
    private final UserRepository userRepository;

    public User getByMobile(String mobile){
        return userRepository.findByMobile(mobile).orElseThrow(()->new UserNotFoundException("不存在这样的用户"));
    }

    public void save(User user){
        Assert.notNull(user.getMobile(), "电话号码不能为空");
        Optional<User> userOptional = userRepository.findByMobile(user.getMobile());
        if (userOptional.isPresent()){
            throw new UserExistedException("该用户已存在,不能重复创建");
        }
        userRepository.save(user);
    }

    public User getById(Integer id){
        Assert.notNull(id, "查询主键不能为空");
        Optional<User> userOptional = userRepository.findById(id);
        if (userOptional.isPresent()){
            return userOptional.get();
        }
        throw new UserNotFoundException("不存在的用户主键:" + id);
    }

    public List<User> getAll(){
        return userRepository.findAll();
    }
}

spring security的账户安全认证相关类:SecurityUser、SecurityUserDetailsService 

import com.example.oauth2.role.entity.Role;
import com.example.oauth2.user.entity.User;
import lombok.Getter;
import lombok.Setter;

import java.util.HashSet;
import java.util.Set;

@Getter
@Setter
public class SecurityUser {
    private Integer id;
    private String username;
    private String password;
    private String phone;
    private Boolean disabled;
    private Boolean locked;
    private Set<Role> roles;

    public SecurityUser(User user){
        this.id = user.getId();
        this.username = user.getName();
        this.password = user.getPassword();
        this.phone = user.getMobile();
        this.disabled = user.getDisabled();
        this.locked = user.getLocked();
        Set<Role> roles = new HashSet<>();
        if (null != user.getRoles() && user.getRoles().size() > 0){
            for (Role role: user.getRoles()){
                if (!role.getDisabled()){
                    roles.add(role);
                }
            }
        }
        this.roles = roles;
    }
}
import com.example.oauth2.exception.UserNotFoundException;
import com.example.oauth2.security.user.SecurityUser;
import com.example.oauth2.user.service.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
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 java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class SecurityUserDetailsService implements UserDetailsService {
    private final UserService userService;

    @Override
    public UserDetails loadUserByUsername(String mobile) {
        try{
            SecurityUser user = new SecurityUser(userService.getByMobile(mobile));

            return new User(
                    user.getPhone(),
                    user.getPassword(),
                    !user.getDisabled(),
                    true,
                    true,
                    !user.getLocked(),
                    user.getRoles().stream().map(role -> new SimpleGrantedAuthority(role.getName()))
                            .collect(Collectors.toList())
            );
        }catch (UserNotFoundException e){
            throw new UsernameNotFoundException(e.getMessage());
        }
    }
}

自定义异常类:UserNotFoundException、UserExistedException 

public class UserNotFoundException extends RuntimeException{
    public UserNotFoundException(String  message){
        super(message);
    }

    public UserNotFoundException(String message, Throwable cause){
        super(message, cause);
    }
}
public class UserExistedException extends RuntimeException{
    public UserExistedException(String message){
        super(message);
    }

    public UserExistedException(String message, Throwable cause){
        super(message, cause);
    }
}

猜你喜欢

转载自blog.csdn.net/miaowansheng/article/details/128151672