web-dev-qa-db-ja.com

Spring Security、Method Securityアノテーション(@Secured)が機能していません(Java config)

@Secured( "ADMIN")(XMLなし、Java config、Spring Boot)のみ)を使用してメソッドセキュリティアノテーションを設定しようとしていますが、ロール経由のアクセスは機能しません。

セキュリティ構成:

_@Configuration
@EnableWebSecurity
public class AppSecurityConfiguration extends WebSecurityConfigurerAdapter{

.....

@Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .antMatchers("/api/**").fullyAuthenticated().and()
                .addFilterBefore(tokenAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
    }

.....

}
_

コントローラーのメソッドへのアクセスを制限したい:

_@RestController
@RequestMapping("/api/groups")
public class GroupController {

    @Autowired
    private GroupService groupService;

    @Secured("ADMIN")
    @RequestMapping
    public List<Group> list() {
        return groupService.findAll();
    }

}
_

URLによるアクセスの制限は機能しています。

_.antMatchers("/api/**").hasAuthority("ADMIN")
_

ロールで制限することを指定するのを忘れたのでしょうか?

PD:ルールにより、どのレイヤーで@PreAuthorize("hasRole('ADMIN')")がコントローラーレイヤーまたはサービスレイヤーにある必要がありますか?

16
silverhawk

この問題は解決されました。

@EnableGlobalMethodSecurity(prePostEnabled = true)を追加します

_@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class AppSecurityConfiguration extends WebSecurityConfigurerAdapter{
}
_

そして、コントローラーで@Secured("ADMIN")@PreAuthorize("hasRole('ADMIN')")に変更しました

4
silverhawk

親切にこれを追加してください

@EnableGlobalMethodSecurity(securedEnabled = true)

この要素は、(要素に適切な属性を設定することにより)アプリケーションで注釈ベースのセキュリティを有効にし、@Secured専用にアプリケーションコンテキスト全体に適用されるセキュリティポイントカット宣言をグループ化するためにも使用されます。したがって、コードは次のようになります

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class AppSecurityConfiguration extends WebSecurityConfigurerAdapter{..
30
Mudassar

コントローラのメソッドセキュリティが機能しない多くの理由があります。

第一に、Spring Securityマニュアルで例として引用されていないためです...冗談ですが、行きたくない場所でSpringツールを使用するのは難しいかもしれません。

さらに深刻なのは、すでに@Mudassarが言ったようにメソッドセキュリティを有効にすることです。マニュアルによれば:

任意の@EnableGlobalMethodSecurityインスタンスで@Configuration注釈を使用して、注釈ベースのセキュリティを有効にできます。たとえば、次の例では、Spring Securityの@Secured注釈が有効になります。

@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true)
public class MethodSecurityConfig {
   // ...
}

Mudassarの答えはここまで正しいことに注意してください。

ただし、メソッドセキュリティはAOPに基づいており、デフォルトではinterfacesでJDKプロキシを使用します。サービスクラスは通常、コントローラーとしてインターフェイスとして挿入されるため、すべての例でサービスレイヤーにメソッドセキュリティが適用されるのはこのためです。

もちろん、コントローラー層で使用できますが、

  • すべてのコントローラーがすべての@Securedアノテーション付きメソッドを実装している
  • または、クラスプロキシに切り替える必要があります

私が従おうとするルールは次のとおりです。

  • uRLを保護したい場合は、HTTPSecurityに固執します
  • よりきめ細かいアクセスを許可する必要がある場合は、サービス層でセキュリティを追加します
12
Serge Ballesta

私はこのスレッドが非常に古いことを知っており、私の答えはこのスレッドのさまざまな人々による答えの一部を暗示しています。しかし、ここに落とし穴と答えのリストを組み合わせたリストがあります:

  1. @Securedを使用し、ロール名が(例)ADMINの場合;これは、@ Secured( "ROLE_ADMIN")の注釈を意味します。
  2. WebSecurityConfigurerAdapterには@EnableGlobalMethodSecurity(securedEnabled = true)が必要です
  3. ほとんどのSpring関連プロキシと同様に、クラスとセキュリティで保護されたメソッドが決して最終的なものではないことを確認してください。 Kotlinの場合、これはすべてのメソッドとクラスを「開く」ことを意味します。
  4. クラスとそのメソッドが仮想(「オープン」)の場合、インターフェースの暗黙の必要性はありません。

動作するKotlinの例の一部を次に示します。

@RestController
@RequestMapping("api/v1")

    open class DiagnosticsController {
        @Autowired
        lateinit var systemDao : SystemDao

        @RequestMapping("ping", method = arrayOf(RequestMethod.GET))
        @Secured("ROLE_ADMIN")
        open fun ping(request : HttpServletRequest, response: HttpServletResponse) : String { ... 
    }

そして

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
open class WebSecurityConfig : WebSecurityConfigurerAdapter() {

よろしく

10
user1210708

私は自分の決定を共有したいと思います。それが役に立つかもしれません。

使用済みspring mvc+ spring security、version 4.2.9.RELEASE

たとえば、@ Securedアノテーションが付いたメソッドを持つサービスがあります

@Secured("ACTION_USER_LIST_VIEW")
List<User> getUsersList();

しかし、GlobalMethodSecurityConfigurationにはinsideメソッドがあるため、機能しませんでした。

protected AccessDecisionManager accessDecisionManager()

new RoleVoter()をデフォルトのrolePrefix = "ROLE_";で初期化した(これにより、beanを使用してrolePrefixを設定することができなくなります)RoleVoter'ROLE_'で始まる値

この問題を解決するには、GlobalMethodSecurityConfigurationこのようにオーバーライドします

@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true)
public class AppMethodSecurityConfiguration extends GlobalMethodSecurityConfiguration {
    @Override
    protected AccessDecisionManager accessDecisionManager() {
        List<AccessDecisionVoter<? extends Object>> decisionVoters = new ArrayList<>();
        ExpressionBasedPreInvocationAdvice expressionAdvice = new ExpressionBasedPreInvocationAdvice();
        expressionAdvice.setExpressionHandler(getExpressionHandler());
        decisionVoters.add(getRoleVoter());
        decisionVoters.add(new AuthenticatedVoter());
        return new AffirmativeBased(decisionVoters);
    }

    private RoleVoter getRoleVoter() {
        RoleVoter e = new RoleVoter();
        e.setRolePrefix("");
        return e;
    }
}
2
Igor

@secured(ADMIN)の代わりに@secured(ROLE_ADMIN)を使用する必要があります。ロール名の前に"ROLE _"と書く必要があります。以下の例では、Adminロールを持つユーザーのみがlist()メソッドにアクセスできることを確認しています。

@RestController
@RequestMapping("/api/groups")
public class GroupController {

    @Autowired
    private GroupService groupService;

    @Secured("ROLE_ADMIN")
    @RequestMapping
    public List<Group> list() {
        return groupService.findAll();
    }

}
1
Sadiq Ali

たぶん、AppSecurityConfigurationをWebMvcConfigと同じコンテキストに登録する必要があります(WebMvcConfigurerAdapterを拡張します)。

AnnotationConfigWebApplicationContext mvcContext = new AnnotationConfigWebApplicationContext();      
mvcContext.register(WebMvcConfig.class, SecurityConfig.class);
0
digz6666