2017-11-15 19 views
1

Spring Securityを使用してBasic AuthでSpring Rest APIを保護しようとしています。ユーザーがデータベースに格納され、ロールに応じて異なるエンドポイントにアクセスできるように構成することをお勧めします。 簡潔にするために、以下の例では、すべてのエンドポイントに「ADMIN」ロールが必要です。 私はすべての設定を(いくつかのオンラインチュートリアルに基づいて)正しく行ったと思うが、セキュリティが私のUserAuthorities(ロール)を比較することはできないようだ。 私は郵便配達員を通じてGETリクエストを送信し、ユーザー名とパスワードを使用して承認すると、私のユーザーが見つかりました(私は401を取得しません)が、ユーザーに適切な役割がないかのように403が表示されます。私が(hasRole(Role.ADMIN.name()) to authenticated()を変更した場合、それはうまく動作します。あなたは私のコードを見て、私が逃しているものを理解するのを助けてくれますか? Userクラス:Spring Security for REST APIを使用したBasic Authのユーザ権限

@Entity 
@NoArgsConstructor 
@Table(name = "users") 
public class User implements UserDetails { 
    @Id 
    @GeneratedValue 
    private Long id; 
    @Column(nullable = false, unique = true) 
    private String username; 
    private String password; 
    @ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.PERSIST) 
    private Set<UserAuthority> authorities = new HashSet<UserAuthority>(); 

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

    public void addAuthority(UserAuthority authority) { 
     authorities.add(authority); 
    } 

    public Collection<? extends GrantedAuthority> getAuthorities() { 
     return authorities; 
    } 

    public String getPassword() { 
     return password; 
    } 

    public String getUsername() { 
     return username; 
    } 

    public boolean isAccountNonExpired() { 
     return true; 
    } 

    public boolean isAccountNonLocked() { 
     return true; 
    } 

    public boolean isCredentialsNonExpired() { 
     return true; 
    } 

    public boolean isEnabled() { 
     return true; 
    } 

    public Long getId() { 
     return id; 
    } 

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

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

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

    public void setAuthorities(Set<UserAuthority> authorities) { 
     this.authorities = authorities; 
    } 
} 

UserAuthorityはクラス:

@Entity 
@Table(name = "authorities") 
@NoArgsConstructor 
@Getter 
@Setter 
public class UserAuthority implements GrantedAuthority { 
    @Id 
    @GeneratedValue 
    private Long id; 
    private String name; 

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

    public String getAuthority() { 
     return name; 
    } 

    @Override 
    public boolean equals(Object o) { 
     if (this == o) return true; 
     if (o == null || getClass() != o.getClass()) return false; 

     UserAuthority authority = (UserAuthority) o; 

     return name != null ? name.equals(authority.name) : authority.name == null; 
    } 

    @Override 
    public int hashCode() { 
     return name != null ? name.hashCode() : 0; 
    } 
} 

セキュリティの設定クラス:

@Configuration 
@EnableWebSecurity 
public class SecurityConfiguration extends WebSecurityConfigurerAdapter { 

    private static String REALM = "MY_TEST_REALM"; 
    //to be a bean later 
    private PasswordEncoder passwordEncoder = new StandardPasswordEncoder(); 
    @Autowired 
    UserDetailsService userDetailsService; 

    @Autowired 
    public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception { 
     auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder); 
    } 

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

     http.csrf().disable() 
       .authorizeRequests() 
       .antMatchers("/**").hasRole(Role.ADMIN.name()) 
       .and().httpBasic().realmName(REALM).authenticationEntryPoint(getBasicAuthEntryPoint()) 
       .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);//We don't need sessions to be created. 
    } 

    @Bean 
    public CustomBasicAuthenticationEntryPoint getBasicAuthEntryPoint() { 
     return new CustomBasicAuthenticationEntryPoint(); 
    } 

    /* To allow Pre-flight [OPTIONS] request from browser */ 
    @Override 
    public void configure(WebSecurity web) throws Exception { 
     web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**"); 
    } 
} 
UserServiceImplクラスの

重要な部分:

@Service 
public class UserServiceImpl implements UserService { 

    @Autowired 
    private UserRepository userRepository; 

    @Autowired 
    private UserAuthorityRepository userAuthorityRepository; 
    private PasswordEncoder passwordEncoder = new StandardPasswordEncoder(); 

    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException { 
     return userRepository.getUserByUserName(s); 
    } 
} 

応答Iグラムetは403です:サーバーは要求を理解しましたが、許可することを拒否しました。

userRepository.getUserByUserName(s)適切な権限を持つ適切なUserオブジェクトを返します。

コードが大変残念ですが、間違いがある可能性があるという手がかりはありません。 ありがとうございました! 乾杯。

答えて

0

私はそれを解決しました。役割は、接頭辞「ROLE_」を永続化する必要が判明したので、私は私の役割の列挙にこれを追加しました:

private static final String ROLE_PREFIX = "ROLE_"; 

public String nameWithPrefix() { 
    return ROLE_PREFIX + name(); 
} 

は、今では動作します:)