Spring端点在检查角色时始终返回403

时间:2018-11-15 06:50:37

标签: java spring-boot spring-security spring-data-jpa

我已经集成了role,并希望根据角色来管理特定服务的访问。 管理员可以创建一个代理,并且该代理位于ADMIN用户组之下。

我基本上创建了一个1 to Many关系飞船,因为我的用户只能拥有一个角色。

@Entity
@Table(name = "role")
public class Role {

    private Long id;
    private String name;
    private Collection<User> users;

    public Role() {
    }

    public Role(String name) {
        this.name = name;
    }

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @OneToMany(mappedBy = "role", cascade = CascadeType.ALL)
    public Collection<User> getUsers() {
        return users;
    }

    public void setUsers(Collection<User> users) {
        this.users = users;
    }
}

在这里,我有一个用户,该用户的组关系以及该组也是1 TO MANY,因为user_admin可以有多个代理,但是代理不能有多个管理员。

@Entity
@Table(name = "user")
public class User {
    private long id;
    private String username;
    private String password;
    private boolean enabled = false;
    private Role role;
    private UserGroup userGroup;

    public User() {
    }

    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }

    public User(String username, String password, Role role) {
        this.username = username;
        this.password = password;
        this.role = role;
    }

    public User(String username, String password, boolean enabled, Role role, UserGroup userGroup) {
        this.username = username;
        this.password = password;
        this.enabled = enabled;
        this.role = role;
        this.userGroup = userGroup;
    }

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    @NotBlank
    @Column(nullable = false, updatable = false, unique = true)
    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    @NotBlank
    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }


    @Column(nullable = false, updatable = true)
    public boolean isEnabled() {
        return enabled;
    }

    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }

    @ManyToOne
    @JoinColumn(name = "role_id", referencedColumnName = "id")
    public Role getRole() {
        return role;
    }

    public void setRole(Role role) {
        this.role = role;
    }

    @ManyToOne
    @JoinColumn(name = "user_group_id", referencedColumnName = "id")
    public UserGroup getUserGroup() {
        return userGroup;
    }

    public void setUserGroup(UserGroup userGroup) {
        this.userGroup = userGroup;
    }
}

在创建用户时,我还要指定角色和组。

SecurityConfig中,我进行了如下配置。

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.cors().and().csrf().disable().authorizeRequests()
            .antMatchers(Constants.BASE_URL_FILE_UPLOADER + Constants.URL_UPLOAD_FILE).hasRole("ADMIN")                                .anyRequest().authenticated()
            .and()
            .addFilter(new JWTAuthenticationFilter(authenticationManager()))
            .addFilter(new JWTAuthorizationFilter(authenticationManager()))
            // this disables session creation on Spring Security
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    http.exceptionHandling().authenticationEntryPoint(new ContentSearcherAuthenticationEntryPoint());
}

但是,如果我用管理员用户访问此端点,则会抛出禁止,并且在访问authentication.getAuthorities()时也会在函数中抛出 emptyList < / p>

ResponseEntity<JsonNode> uploadFile(@RequestParam("file") MultipartFile file, Authentication authentication) {
    logger.info("Authentication is [{}] and user is [{}]", authentication.getAuthorities(), authentication.getName()); // []
}

我对UserDetailsService感到困惑,我也像这样添加了GrantedAuthority

@Service
public class UserDetailsServiceImpl implements UserDetailsService {
    private UserRepository userRepository;
    private RoleRepository roleRepository;

    public UserDetailsServiceImpl(UserRepository userRepository, RoleRepository roleRepository) {
        this.userRepository = userRepository;
        this.roleRepository = roleRepository;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findUserByUsername(username);
        if (user == null) {
            throw new UsernameNotFoundException(username + " Not Exists");
        }
        user.setEnabled(true);
        userRepository.save(user);
        return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), user.isEnabled(),
                true, true, true, getAuthorities(user.getRole()));
    }

    private Collection<? extends GrantedAuthority> getAuthorities(
            Role role) {

        List<GrantedAuthority> authorities = new ArrayList<>();
        authorities.add(new SimpleGrantedAuthority(Constants.ROLE_PREFIX + role.getName()));

        return authorities;
    }
}

我所缺少的是我还必须添加其他配置吗?

我正在使用JWT进行身份验证,因此也应该在其中添加一些内容吗?

因为当我在JWT Authentication中获得successfulAuthentication时,它会显示权限。

@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
    logger.info("Auth in the successful is [{}]", authResult.getAuthorities()); // [ROLE_ADMIN]
}

使用Spring-Security核心5.0.9。

1 个答案:

答案 0 :(得分:0)

我从@Reza Nasiri问题获得提示后就做到了,基本上我现在所做的是在认证Authorities令牌时没有添加JWT

return new UsernamePasswordAuthenticationToken(user, null, getAuthorities("ADMIN");

在我的getAuthentication类的JWTAuthorizationFilter函数中。