bestsource

스프링 MVC - 스프링 보안을 통해 사용자가 이미 로그인되어 있는지 확인?

bestsource 2023. 9. 6. 22:11
반응형

스프링 MVC - 스프링 보안을 통해 사용자가 이미 로그인되어 있는지 확인?

저는 Spring MVC 어플이 있습니다.자체 사용자 지정 로그인 페이지를 사용합니다.로그인 성공 시 'LOGGED_'IN_USER' 개체가 HTTPS 세션에 배치됩니다.

인증된 사용자만 URL에 액세스할 수 있도록 하고 싶습니다.저는 웹 필터를 사용함으로써 이를 달성할 수 있다는 것을 알고 있습니다.그러나 이 부분은 Spring Security를 사용하여 수행하고 싶습니다(제 수표는 그대로 유지됩니다 - 'LOGGED_'를 찾아보세요).HTTPS 세션의 IN_USER' 개체(존재하는 경우 로그인).

현재 로그인 동작을 변경할 수 없습니다. 아직 Spring Security를 사용하지 않습니다.

Spring Security의 어떤 측면을 사용하여 단독으로 이 부분을 달성할 수 있습니까? 요청이 (로그인한 사용자로부터) 인증되었는지 확인합니다.

최소 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>

@보안 주석 기준

요망하는<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(Prefix 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;
     }
}

2.) 확장이 필요합니다.DefaultWebSecurityExpressionRootHandler사용자 정의 표현 루트를 제공하는 핸들러가 있는 경우

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

스프링 시큐리티 3.1 업데이트

Spring Security 3.1 이후로 사용자 정의 표현을 구현하기가 좀 더 쉽습니다.더 이상 서브클래스를 할 필요가 없습니다.WebSecurityExpressionHandler오버라이드(override)createEvaluationContext. 대신 서브글라스 하나AbstractSecurityExpressionHandler<FilterInvocation>또는 그 하위 클래스.DefaultWebSecurityExpressionHandlere드)를 합니다.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;
      }
 }

다른 솔루션으로 클래스를 생성할 수 있습니다.

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:

이전 해결책에 문제가 있는데, 이것은 Peter를 주석으로 설명합니다.

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

이것이 당신이 이루고자 하는 것입니까?

<c:choose>
  <c:when test="${pageContext.request.userPrincipal.authenticated}">Show something</c:when>
  <c:otherwise>Show something else</c:otherwise>
</c:choose>

많은 인증 공급자가 UserDetails 개체를 주체로 만듭니다.

한 또 은 Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ ΔΔΔ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Authentication.getPrincipal()다의 한 입니다.UserDetails됩니다; "anonymousUser"(String 입니다.) 기본값입니다.

boolean isUserLoggedIn(){
   return SecurityContextHolder.getContext().getAuthentication().getPrincipal() instanceof UserDetails
}

WebSecurityConfigureAdapter를 확장하는 클래스를 만들고 일치하는 URL인증된 클래스를 추가할 수 있습니다.

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

당신은 가도 좋습니다.

다음과 같은 엔드포인트를 만들었습니다.

    @GetMapping("/api/authorize")
    public boolean isUserLoggedIn() {
        boolean isLoggedIn = false;
        try {
            SecurityContextHolder.getContext().getAuthentication().getPrincipal();
            isLoggedIn = true;
        } catch (Exception e) {
            isLoggedIn = false;
        }
        return isLoggedIn;
    }

언급URL : https://stackoverflow.com/questions/12371770/spring-mvc-checking-if-user-is-already-logged-in-via-spring-security

반응형