如何根据弹簧安全性对API的角色正确限制访问?

时间:2016-08-22 07:22:37

标签: java spring authentication spring-security roles

我想根据用户角色保护我的API,但@PreAuthorize Annotations似乎无法正常工作。无论用户具有什么角色,服务器都会抛出403错误。如何使这项工作?

这是我在自定义身份验证提供程序中检索用户详细信息的地方:

   @Override
    protected UserDetails retrieveUser(String userName, UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken){
        final String password = (String) usernamePasswordAuthenticationToken.getCredentials();

        if (!StringUtils.hasText(password)) {
            this.logger.warn("Username {}: no password provided", userName);
        }

        userName = parseCredentials(userName);

        try {
            DirContext ctx = ldapConfiguration.openConnection(userName, password);
            ctx.close();
        } catch (NamingException e) {
            throw new LdapException("User not found in Active Directory", e);
        } catch (NullPointerException e) {
            throw new CredentialsNotProvidedException("Entered data may be null", e);
        }

        User user = userRepository.findOneByLogin(userName);

        if (user == null) {
            this.logger.warn("Username {}: user not found", userName);
            throw new BadCredentialsException("Invalid Username/Password for user " + userName);
        }

        final List<GrantedAuthority> auths = new ArrayList<GrantedAuthority>();

        GrantedAuthority r = (GrantedAuthority) () -> "ROLE_" + user.getRole().getName().toUpperCase();
        auths.add(r);
        // enabled, account not expired, credentials not expired, account not locked
        UserDetails userDetails = new org.springframework.security.core.userdetails.User(userName, password, true, true, true, true, auths);
        return userDetails;
    }

这是控制器:

@PreAuthorize("hasRole('ROLE_HR')") //I don't have acces even if I am HR
@RestController
public class SettingsController {

    @Autowired
    private LocationRepository locationRepository;
    @Autowired
    private DepartmentRepository departmentRepository;
    @Autowired
    private RoleRepository roleRepository;

    @RequestMapping(value = "/api/locations", method = RequestMethod.POST)
    public ResponseEntity addLocation(@RequestBody Location location) {
        if (location == null) {
            return new ResponseEntity(HttpStatus.BAD_REQUEST);
        }
        locationRepository.save(new Location(location.getName()));
        return new ResponseEntity(HttpStatus.CREATED);
    }

    @RequestMapping(value = "/api/roles", method = RequestMethod.POST)
    public ResponseEntity addRole(@RequestBody Role role) {
        if (role == null) {
            return new ResponseEntity(HttpStatus.BAD_REQUEST);
        }
        roleRepository.save(new Role(role.getName()));
        return new ResponseEntity(HttpStatus.CREATED);
    }

    @RequestMapping(value = "/api/departments", method = RequestMethod.POST)
    public ResponseEntity addDepartment(@RequestBody Department department) {
        if (department == null) {
            return new ResponseEntity(HttpStatus.BAD_REQUEST);
        }
        departmentRepository.save(new Department(department.getName()));
        return new ResponseEntity(HttpStatus.CREATED);
    }
}

安全配置:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private DatabaseAuthenticationProvider authenticationProvider;

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/js/**", "/css/**", "/img/**");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.formLogin().loginPage("/login").failureUrl("/login").defaultSuccessUrl("/")
                .and().logout().logoutSuccessUrl("/login")
                .and().authorizeRequests().antMatchers("/login").permitAll()
                /*.antMatchers("/settings.html").access("hasRole('HR')")
                .antMatchers("/pendingRequests.html").access("hasRole('MANAGER')")
                .antMatchers("/settings.html","/pendingRequests.html").access("hasRole('ADMIN')")*/
                .anyRequest().authenticated().and().csrf().disable();
    }



    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(authenticationProvider).eraseCredentials(false);
    }
}

1 个答案:

答案 0 :(得分:1)

根据安全配置类中的注释行 .antMatchers("/settings.html").access("hasRole('HR')")用户角色是HR。

如果角色为 HR ,那么您应该使用 @PreAuthorize("hasRole('HR')")

并且@PreAuthorize也应先放置,然后提及@RestController

@RestController
@PreAuthorize("hasRole('HR')")
public class SettingsController