47

SpringMVCアプリケーションがあります。独自のカスタムログインページを使用します。ログインに成功すると、「LOGGED_IN_USER」オブジェクトがHTTPSessionに配置されます。

認証されたユーザーのみにURLへのアクセスを許可したい。私はウェブフィルターを使用することでこれを達成できることを知っています。しかし、この部分はSpring Securityを使用して実行したいと思います(私のチェックは同じままです。ログインしている場合は、HTTPSessionで「LOGGED_IN_USER」オブジェクトを探してください)。

私の制約は、現在ログイン動作を変更できないことです-それはまだSpringSecurityを使用しません。

この部分を単独で達成するためにSpringSecurityのどの側面を使用できますか?要求が(ログインしたユーザーから)認証されているかどうかを確認しますか?

4

6 に答える 6

125

少なくとも4つの異なる方法があります。

春のセキュリティXML構成

これが最も簡単な方法です

<security:http auto-config="true" use-expressions="true" ...>
   ...
  <security:intercept-url pattern="/forAll/**" access="permitAll" />
  <security:intercept-url pattern="/**" access="isAuthenticated()" />
</security:http>

@Securedアノテーションごと

必要<global-method-security secured-annotations="enabled" />

@Secured("ROLE_ADMIN")
@RequestMapping(params = "onlyForAdmins")    
public ModelAndView onlyForAdmins() {
    ....
}

@PreAuthorizeアノテーションごと

必要<global-method-security pre-post-annotations="enabled" />

 @PreAuthorize("isAuthenticated()")
 @RequestMapping(params = "onlyForAuthenticated")
 public ModelAndView onlyForAuthenticatedUsers() {
     ....
 }

プログラマティック

 SecurityContextHolder.getContext().getAuthentication() != null &&
 SecurityContextHolder.getContext().getAuthentication().isAuthenticated() &&
 //when Anonymous Authentication is enabled
 !(SecurityContextHolder.getContext().getAuthentication() 
          instanceof AnonymousAuthenticationToken) 

カスタム式

組み込みの式では不十分な場合は、それらを拡張できます。メソッドアノテーションのSpEL式を拡張する方法については、たとえば次のように説明します。

しかし、インターセプターの<security:intercept-url ... access="myCustomAuthenticatedExpression" />場合、プライベートクラスの問題に対処する必要がない、わずかに異なるアプローチが可能です。--Spring Security 3.0でのみ実行しましたが、3.1でも機能することを願っています。

1.)から拡張する新しいクラスを作成する必要がありますWebSecurityExpressionRoot(プレフィックスWebは重要な部分です!)。

public class MyCustomWebSecurityExpressionRoot
         extends WebSecurityExpressionRoot {
     public MyCustomWebSecurityExpressionRoot(Authentication a,
                 FilterInvocation f) {
          super(a, f);
     }

     /** That method is the one that does the expression evaluation! */
     public boolean myCustomAuthenticatedExpression() {
        return super.request.getSession().getValue("myFlag") != null;
     }
}

DefaultWebSecurityExpressionRootHandler2.)カスタム式のルートを提供するハンドラーを作成するには、を拡張する必要があります

 public class MyCustomWebSecurityExpressionHandler
              extends DefaultWebSecurityExpressionHandler {

      @Override        
      public EvaluationContext createEvaluationContext(Authentication a,
                FilterInvocation f) {
          StandardEvaluationContext ctx =
                   (StandardEvaluationContext) super.createEvaluationContext(a, f);

           WebSecurityExpressionRoot myRoot =
                    new MyCustomWebSecurityExpressionRoot(a, f);

           ctx.setRootObject(myRoot);
           return ctx;
      }
 }

3.)次に、ハンドラーを有権者に登録する必要があります

<security:http use-expressions="true"
 access-decision-manager-ref="httpAccessDecisionManager" ...>
      ...
    <security:intercept-url pattern="/restricted/**"
              access="myCustomAuthenticatedExpression" />         
      ...
</security:http>

<bean id="httpAccessDecisionManager"
      class="org.springframework.security.access.vote.AffirmativeBased">
    <constructor-arg name="decisionVoters">
            <list>
                <ref bean="webExpressionVoter" />
            </list>
    </constructor-arg>
</bean>

<bean id="webExpressionVoter"
      class="org.springframework.security.web.access.expression.WebExpressionVoter">
    <property name="expressionHandler"
              ref="myCustomWebSecurityExpressionHandler" />
</bean>

<bean id="myCustomWebSecurityExpressionHandler"
    class="MyCustomWebSecurityExpressionHandler" />

SpringSecurity3.1アップデート

Spring Security 3.1以降、カスタム式の実装が少し簡単になりました。sublcassWebSecurityExpressionHandlerしてオーバーライドする必要はもうありませんcreateEvaluationContext。代わりに、1つAbstractSecurityExpressionHandler<FilterInvocation>のサブクラスまたはそのサブクラスDefaultWebSecurityExpressionHandlerとオーバーライドSecurityExpressionOperations createSecurityExpressionRoot(final Authentication a, final FilterInvocation f)

 public class MyCustomWebSecurityExpressionHandler
              extends DefaultWebSecurityExpressionHandler {

      @Override        
      public SecurityExpressionOperations createSecurityExpressionRoot(
                Authentication a,
                FilterInvocation f) {
           WebSecurityExpressionRoot myRoot =
                    new MyCustomWebSecurityExpressionRoot(a, f);

           myRoot.setPermissionEvaluator(getPermissionEvaluator());
           myRoot.setTrustResolver(this.trustResolver);
           myRoot.setRoleHierarchy(getRoleHierarchy());
           return myRoot;
      }
 }
于 2012-09-11T14:54:04.230 に答える
18

別の解決策として、クラスを作成できます。

public class AuthenticationSystem {
    public static boolean isLogged() {
        final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        return null != authentication && !("anonymousUser").equals(authentication.getName());
    }
    // ...
    // Any another methods, for example, logout
}

次に、コントローラーで:

@Controller
@RequestMapping(value = "/promotion")
public final class PromotionController {  
    @RequestMapping(value = {"", "/"}, method = RequestMethod.GET)
    public final String root() {
        if (!AuthenticationSystem.isLogged()) return "login"; // or some logic
        // some logic
        return "promotion/index";
    }
}

PS

以前の解決策には問題があり、コメントでピーターを説明しています。

@Controller
@RequestMapping(value = "/promotion")
public final class PromotionController {  
    @RequestMapping(value = {"", "/"}, method = RequestMethod.GET)
    public final String root(final Principal principal) {
        if (null == principal) return "login"; // or some logic
        // some logic
        return "promotion/index";
    }
}
于 2015-08-13T22:21:33.663 に答える
9

これはあなたが達成しようとしていることですか?

<c:choose>
  <c:when test="${pageContext.request.userPrincipal.authenticated}">Show something</c:when>
  <c:otherwise>Show something else</c:otherwise>
</c:choose>
于 2013-02-05T03:35:46.320 に答える
2

認証プロバイダーの多くは、プリンシパルとしてUserDetailsオブジェクトを作成します。

私が見つけたもう1つの方法は、spring-securityを使用して、の戻り値が;Authentication.getPrincipal()のインスタンスであるかどうかを確認することです。UserDetailsメソッドはデフォルトで"anonymousUser"String)を返します。

boolean isUserLoggedIn(){
   return SecurityContextHolder.getContext().getAuthentication().getPrincipal() instanceof UserDetails
}
于 2018-12-31T10:47:38.123 に答える
0

WebSecurityConfigurerAdapterを拡張するクラスを作成し、一致するURLに認証済み を追加するだけです。

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests().antMatchers("/User/**").authenticated()
 }

準備できた

于 2020-12-27T14:10:34.373 に答える
0

次のようなエンドポイントを作成しました。

    @GetMapping("/api/authorize")
    public boolean isUserLoggedIn() {
        boolean isLoggedIn = false;
        try {
            SecurityContextHolder.getContext().getAuthentication().getPrincipal();
            isLoggedIn = true;
        } catch (Exception e) {
            isLoggedIn = false;
        }
        return isLoggedIn;
    }
于 2022-02-14T19:17:17.640 に答える