Spring Boot Oauth 基于登录授权

问题描述 投票:0回答:1

我正在使用oauth创建一个Spring boot应用程序,现在我可以登录github,但我想要一个基于角色的应用程序,所以有些路由只能由role_admin访问,而其他路由可以由role_user访问,我一直在尝试一些东西,但我的代码看起来有点混乱,所以我感谢任何帮助! 现在,在 CustomOAuth2User 类的 getAuthorities 方法中,它显示了 Set Roles = getUserRoles();为空,因此它默认所有用户角色为 role_user,因此我可以访问需要此类角色的路由,但不能访问管理员路由,即使我使用 role_admin 创建用户也是如此。

安全配置

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    
    @Autowired
    private CustomOAuth2UserService oauthUserService;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private UserService userService;

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        return http
        .authorizeHttpRequests(auth -> {
            auth.requestMatchers(HttpMethod.GET, "/userinfo").hasRole("ADMIN");
            auth.requestMatchers(HttpMethod.GET, "/").hasRole("USER");
            auth.anyRequest().authenticated();
        })
         .oauth2Login(oauth2 -> oauth2
                        .userInfoEndpoint(userInfo -> userInfo.userService(oauthUserService)).successHandler(new AuthenticationSuccessHandler() {

                            @Override
                            public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
                                                                Authentication authentication) throws IOException, ServletException {

                                CustomOAuth2User oauthUser = (CustomOAuth2User) authentication.getPrincipal();

                                String github_id = oauthUser.getAttributes().get("id").toString();

                                Optional<User> userExistOp = userRepository.findByIdentifier(github_id);

                                if(!userExistOp.isPresent()) {
                                    //all user are saves with role User
                                    UserDTO userDTO = new UserDTO(oauthUser.getName(),"username", oauthUser.getAttributes().get("id").toString(), oauthUser.getAttributes().get("avatar_url").toString(), Role.ADMIN);

                                    userService.create(userDTO);
                                }

                                response.sendRedirect("/");
                            }
                        })
                )
        .build();
    }
}

自定义OAuth2用户服务

@Service
public class CustomOAuth2UserService extends DefaultOAuth2UserService {

    @Override
    public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
        OAuth2User user =  super.loadUser(userRequest);
        return new CustomOAuth2User(user);
    }
}

自定义Oauth2User

public class CustomOAuth2User implements OAuth2User {

    private OAuth2User oauth2User;

    public CustomOAuth2User(OAuth2User oauth2User) {
        this.oauth2User = oauth2User;
    }

    @Override
    public Map<String, Object> getAttributes() {
        return oauth2User.getAttributes();
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        Set<Role> roles = getUserRoles();

        System.out.println("User roles:");
        for (Role role : roles) {
            System.out.println(role.name());
        }

        if (roles != null && !roles.isEmpty()) {
            // Convert roles to GrantedAuthority objects
            return roles.stream()
                    .map(role -> new SimpleGrantedAuthority("ROLE_" + role.name()))
                    .collect(Collectors.toList());
        } else {
            // Provide a default role if user roles are not available
            return Collections.singleton(new SimpleGrantedAuthority("ROLE_USER"));
        }
    }

    @Override
    public String getName() {
        return oauth2User.getAttribute("name");
    }

    // Helper method to retrieve user roles from OAuth2User attributes
    private Set<Role> getUserRoles() {
        // Assuming roles are stored as an attribute with key "roles" in OAuth2User attributes
        Collection<String> roleStrings = (Collection<String>) oauth2User.getAttribute("roles");
        return roleStrings != null ?
                roleStrings.stream()
                        .map(Role::valueOf) // Convert role string to Role enum
                        .collect(Collectors.toSet()) :
                Collections.emptySet();
    }

    public String getEmail() {
        return oauth2User.<String>getAttribute("email");
    }
}

用户模型

@Entity
@Table(name="users")
@Data
@Setter
public class User implements UserDetails {

    @Id
    @GeneratedValue(strategy= GenerationType.IDENTITY)
    private Long id;

    private String name;

    private String username;

    private String identifier;

    private String avatar;

    private Role role;

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        if (this.role == Role.ADMIN) {
            return List.of(new SimpleGrantedAuthority("ROLE_ADMIN"), new SimpleGrantedAuthority("ROLE_USER"));
        } 
        return List.of(new SimpleGrantedAuthority("ROLE_USER"));
    }

    @Override
    public String getPassword() {
        return null;
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }
}

认证服务

@Service
public class AuthService implements UserDetailsService{

    UserRepository userRepository;

    public AuthService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Override
    public UserDetails loadUserByUsername(String identifier) throws UsernameNotFoundException {
        Optional<User> userOp = userRepository.findByIdentifier(identifier);
        if (!userOp.isPresent()) {
            throw new UsernameNotFoundException("User not found with GitHub user ID: " + identifier);
        }

        User user = userOp.get();
        // Construct UserDetails object with user roles
        return org.springframework.security.core.userdetails.User
                .withUsername(String.valueOf(user.getIdentifier())) // GitHub user ID
                .password(user.getPassword())
                .authorities(user.getAuthorities())
                .accountExpired(true)
                .accountLocked(true)
                .credentialsExpired(true)
                .disabled(true)
                .build();
    }
}

Pom.xml

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.3</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.ecommerce</groupId>
    <artifactId>e-commerce</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>e-commerce</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-oauth2-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.flywaydb</groupId>
            <artifactId>flyway-core</artifactId>
        </dependency>

        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
            <version>1.5.5.Final</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
             <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.11.0</version>
                <configuration>
                    <annotationProcessorPaths>
                        <path>
                            <groupId>org.mapstruct</groupId>
                            <artifactId>mapstruct-processor</artifactId>
                            <version>1.5.5.Final</version>
                        </path>
                    </annotationProcessorPaths>
                </configuration>
            </plugin>
        </plugins>
    </build>
java spring-boot spring-security oauth-2.0
1个回答
0
投票

你应该做的是使用你自己的授权服务器(Keycloak?Auth0?Amazon cognito?有很多选择)。这个新的授权服务器将负责保留角色并将其添加到令牌中。然后,您只需在 Spring 客户端和资源服务器中手动配置权限映射即可。

© www.soinside.com 2019 - 2024. All rights reserved.