首页 > 解决方案 > SpringSecurity configure() 方法配置问题

问题描述

我开发了一个 REST api,其中使用 SpringSecurity 保护方法。

GitHub 链接->项目

它正在工作,但不如预期

SpringSecurity.config
---------------

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter{

    @Autowired
    private UserDetailsService userDetailService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        auth.userDetailsService(userDetailService).passwordEncoder(encode());


    }


    @Override
    protected void configure(HttpSecurity http) throws Exception {


        http
            .csrf().disable();
        http

            .authorizeRequests()
            .antMatchers("/user/**")
            .authenticated()
            .anyRequest()
            .hasAnyRole("USER","ADMIN")
            .and()
            .authorizeRequests()
            .antMatchers("/admin/**")
            .authenticated()
            .anyRequest()
            .hasRole("ADMIN")
            .and()
            .formLogin()
            .permitAll();

        /*http
            .authorizeRequests()
            .antMatchers("/admin/**").hasRole("ADMIN")
            .antMatchers("/user/**").hasAnyRole("USER","ADMIN")
            .anyRequest()
            .authenticated()
            .and()
            .formLogin()
            .permitAll();*/

    }

    @Bean
    public BCryptPasswordEncoder encode() {
        return new BCryptPasswordEncoder();
    }

}

AdminController
----------

@RestController
@RequestMapping("/admin")
public class AdminController {

    @Autowired
    private UserRepo userRepo;
    @Autowired
    private BCryptPasswordEncoder encoder;

    @PostMapping("/add")
    @PreAuthorize("hasRole('ADMIN')")
    public String addUser(@RequestBody User user) {
        String encodedPwd= encoder.encode(user.getPassword());
        user.setPassword(encodedPwd);
        userRepo.save(user);
        return "user added sucessfully...";
    }

    @GetMapping("/demo")
    @PreAuthorize("hasRole('ADMIN')")
    public String getDemo() {
        return "Hi";
    }

}

自定义控制器
--------------

@RestController
@RequestMapping("/user")
public class CustomController {

    @GetMapping("/access")
    @PreAuthorize("hasAnyRole('USER','ADMIN')")
    public String showUser() {

        return "Url Security Provided";
    }
}

CustomUserDetailService
--------------

@Service
public class CustomUserDetailService implements UserDetailsService {

    @Autowired
    private UserRepo userRepo;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        User user= userRepo.findByUsername(username);
        CustomUserDetails userDetails= null;

        if(user!= null) {
            userDetails= new CustomUserDetails();
            userDetails.setUser(user);
        }else {
            throw new UsernameNotFoundException("User Not Found");
        }
        return userDetails;
    }

}


自定义用户详细信息 -----------------

@Getter
@Setter
public class CustomUserDetails implements UserDetails {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private User user;


    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {

        /*return user.getRoles().stream()
            .map(role->new SimpleGrantedAuthority("ROLE_"+ role))
            .collect(Collectors.toList());*/
        return user.getRoles().stream().map(role -> new SimpleGrantedAuthority("ROLE_" + role))
        .collect(Collectors.toList());
    }

    @Override
    public String getPassword() {
        // TODO Auto-generated method stub
        return user.getPassword();
    }

    @Override
    public String getUsername() {
        // TODO Auto-generated method stub
        return user.getUsername();
    }

    @Override
    public boolean isAccountNonExpired() {
        // TODO Auto-generated method stub
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        // TODO Auto-generated method stub
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        // TODO Auto-generated method stub
        return true;
    }

    @Override
    public boolean isEnabled() {
        // TODO Auto-generated method stub
        return true;
    }

    public CustomUserDetails() {
        super();
        // TODO Auto-generated constructor stub
    }

}

用户
----------

@Entity
@Getter
@Setter
@NoArgsConstructor
public class User {

    @Id
    @GenericGenerator(name="gen",strategy="increment")
    @GeneratedValue(generator="gen")
    private int user_id;
    private String username;
    private String password;
    private String email;
    @OneToMany(cascade= CascadeType.ALL, fetch= FetchType.EAGER)
    @JoinTable(name="user_roles",
                    joinColumns= @JoinColumn(referencedColumnName= "user_id"), 
                    inverseJoinColumns= @JoinColumn(referencedColumnName="role_id"))
    private Set<Roles> roles;

}

问题是:通过上述设置,我可以访问用户而不是管理员的 URL

如果我在评论

http
            /*.authorizeRequests()
            .antMatchers("/user/**")
            .authenticated()
            .anyRequest()
            .hasRole("USER")
            .and()*/
            .authorizeRequests()
            .antMatchers("/admin/**")
            .authenticated()
            .anyRequest()
            .hasRole("ADMIN")
            .and()
            .formLogin()
            .permitAll();

然后我可以访问用于ADMIN的URL ,但我缺少对USER的URL的身份验证

同样,如果我在评论admin/则可以访问USER部分。它的行为就像 Ordering 哪个 url 第一个是它识别出的,第二个只是在浏览器中给出 403 而不是在控制台中给出任何东西。

类似于 Order 之类的东西,首先可以访问

有没有我做错的地方。

如果我不发表评论@EnableGlobalSecurity@PreAuthorize我将无法访问任何用于ADMINUSER的URL ,所以我不能错过,因为这些是用于保护 REST API 方法的403@EnableGlobalSecurity@PreAuthorize

标签: springspring-bootspring-security

解决方案


只需为您的管理员角色添加对所有页面的权限。这样,您可以确保您的管理员可以访问他想要的任何页面。

http
            /*.authorizeRequests()
            .antMatchers("/user/**")
            .authenticated()
            .anyRequest()
            .hasRole("USER")
            .and()*/
            .authorizeRequests()
            .antMatchers("/admin/**")
            .hasRole("ADMIN")
            .antMatchers("/user/**")
            .hasAnyRole("ADMIN", "USER")
            .and()
            .formLogin()
            .permitAll();

推荐阅读