Spring MVC-sprawdzanie czy użytkownik jest już zalogowany przez Spring Security?

Mam aplikację Spring MVC.używa własnej strony logowania . Po pomyślnym zalogowaniu obiekt "LOGGED_IN_USER" jest umieszczany w sesji HTTPSession.

Chcę zezwolić tylko uwierzytelnionym użytkownikom na dostęp do adresów URL. Wiem, że mogę to osiągnąć za pomocą filtra internetowego. Ale, ta część chcę zrobić za pomocą Spring Security (moje sprawdzenie pozostanie taka sama-poszukaj 'LOGGED_IN_USER' obiekt w HTTPSession, jeśli obecny jesteś zalogowany).

moim ograniczeniem jest to, że nie mogę zmienić Zachowanie logowania w chwili obecnej - które nie będzie jeszcze korzystać z Spring Security.

Jakiego aspektu Spring Security mogę użyć, aby osiągnąć tę część samodzielnie - sprawdzić, czy żądanie jest uwierzytelnione (od zalogowanego użytkownika)?

Author: Jasper, 2012-09-11

3 answers

Istnieją co najmniej 4 różne sposoby:

Spring security XML configuration

To najprostszy sposób

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

Per @ Zabezpieczona Adnotacja

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

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

Per @ Preautoryzuj Adnotację

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

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

Programmatic

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

Wyrażenie Własne

Jeśli wbudowane wyrażenia nie wystarczą, możesz je rozszerzyć. Jak rozszerzyć wyrażenia SpEL dla adnotacji metody jest omówione na przykład tutaj:

Ale dla interceptor {[10] } jest nieco inne podejście możliwe, że nie trzeba radzić sobie z problemem klasy prywatnej. -- zrobiłem to tylko dla Spring Security 3.0, ale mam nadzieję, że zadziała również dla 3.1.

1.) musisz utworzyć nową klasę, która rozciąga się od WebSecurityExpressionRoot (prefiks Web jest ważnym część!).

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;
     }
}

2.) potrzebujesz rozszerzenia DefaultWebSecurityExpressionRootHandler, aby mieć obsługę, która zapewnia root twojego wyrażenia niestandardowego

 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. Następnie musisz zarejestrować swojego opiekuna u wyborców

<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" />

Spring Security 3.1 Update

Od wersji Spring Security 3.1 nieco łatwiej jest zaimplementować własne wyrażenie. Nie trzeba już podlinkować WebSecurityExpressionHandler i nadpisywać createEvaluationContext. Zamiast jednej podklasy AbstractSecurityExpressionHandler<FilterInvocation> lub jej podklasy DefaultWebSecurityExpressionHandler i nadpisać 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;
      }
 }
 97
Author: Ralph,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:03:02

Inne rozwiązanie, można sprawdzić principal w metodach kontrolera:

@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";
    }
}
 13
Author: Alexey Nikitenko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-03 19:49:24

Czy to właśnie próbujesz osiągnąć?

<c:choose>
  <c:when test="${pageContext.request.userPrincipal.authenticated}">Show something</c:when>
  <c:otherwise>Show something else</c:otherwise>
</c:choose>
 9
Author: Christopher Yang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-05 03:35:46