스프링

 

버전 업 참조 :

★★★ 스프링부트 시큐리티 세션정보 변경 , Spring Security는 사용자 세션을 업데이트하는 방법

 

 

권한을 업데이트하려면 두 곳에서 인증 오브젝트를 수정.

하나는 보안 컨텍스트에 있고 다른 하나는 요청 컨텍스트. 

주요 객체는 org.springframework.security.core.userdetails.User이거나 해당 클래스를 확장.

(UserDetailsService를 재정의 한 경우). 이것은 현재 사용자를 수정하는 데 사용

.

로그인 한 사용자에 대해 스프링 세션을 사용하여 세션을 업데이트하려면 사용자 정의 필터가 필요합니다. 필터는 일부 프로세스에 의해 수정 된 세션 세트를 저장합니다. 메시징 시스템은 새 세션을 수정해야 할 때 해당 값을 업데이트.

 

요청에 일치하는 세션 키가있는 경우 필터는 데이터베이스에서 사용자를 조회하여 업데이트를 가져옵니다. 그런 다음 세션의 "SPRING_SECURITY_CONTEXT"속성을 업데이트하고 SecurityContextHolder의 인증을 업데이트.

사용자는 로그 아웃 할 필요가 없음

 

 

Authentication newAuth = new UsernamePasswordAuthenticationToken({YourPrincipalObject},null,List)

 SecurityContextHolder.getContext().setAuthentication(newAuth);
 RequestContextHolder.currentRequestAttributes().setAttribute("SPRING_SECURITY_CONTEXT", newAuth, RequestAttributes.SCOPE_GLOBAL_SESSION);

 

 

@Component
@Order(UpdateAuthFilter.ORDER_AFTER_SPRING_SESSION)
public class UpdateAuthFilter extends OncePerRequestFilter
{
public static final int ORDER_AFTER_SPRING_SESSION = -2147483597;

private Logger log = LoggerFactory.getLogger(this.getClass());

private Set permissionsToUpdate = new HashSet<>();

@Autowired
private UserJPARepository userJPARepository;

private void modifySessionSet(String sessionKey, boolean add)
{
    if (add) {
        permissionsToUpdate.add(sessionKey);
    } else {
        permissionsToUpdate.remove(sessionKey);
    }
}

public void addUserSessionsToSet(UpdateUserSessionMessage updateUserSessionMessage)
{
    log.info("UPDATE_USER_SESSION - {} - received", updateUserSessionMessage.getUuid().toString());
    updateUserSessionMessage.getSessionKeys().forEach(sessionKey -> modifySessionSet(sessionKey, true));
    //clear keys for sessions not in redis
    log.info("UPDATE_USER_SESSION - {} - success", updateUserSessionMessage.getUuid().toString());
}

@Override
public void destroy()
{

}

@Override
protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException
{
    HttpSession session = httpServletRequest.getSession();

if (session != null)
{
    String sessionId = session.getId();
    if (permissionsToUpdate.contains(sessionId))
    {
        try
        {
            SecurityContextImpl securityContextImpl = (SecurityContextImpl) session.getAttribute("SPRING_SECURITY_CONTEXT");
            if (securityContextImpl != null)
            {
                Authentication auth = securityContextImpl.getAuthentication();
                Optional user = auth != null
                                      ? userJPARepository.findByUsername(auth.getName())
                                      : Optional.empty();

                if (user.isPresent())
                {
                    user.get().getAccessControls().forEach(ac -> ac.setUsers(null));

                    MyCustomUser myCustomUser = new MyCustomUser (user.get().getUsername(),
                                                                 user.get().getPassword(),
                                                                 user.get().getAccessControls(),
                                                                 user.get().getOrganization().getId());

                    final Authentication newAuth = new UsernamePasswordAuthenticationToken(myCustomUser ,
                                                                                           null,
                                                                                           user.get().getAccessControls());
                    SecurityContextHolder.getContext().setAuthentication(newAuth);
                    session.setAttribute("SPRING_SECURITY_CONTEXT", newAuth);
                }
                else
                {
                    //invalidate the session if the user could not be found
                    session.invalidate();
                }
            }
            else
            {
                //invalidate the session if the user could not be found
                session.invalidate();
            }
        }
        finally
        {
            modifySessionSet(sessionId, false);
        }
    }
}

filterChain.doFilter(httpServletRequest, httpServletResponse);
}

 

 

 

예)

1

    	/** 스프링 시큐리티 세션  변경 처리 */
    	//세션 초기화
    	SecurityContextHolder.clearContext();
    	UserDetails updateUserDetails = new PrincipalDetails(memberDto);
	Authentication newAuthentication = new UsernamePasswordAuthenticationToken(updateUserDetails, null, updateUserDetails.getAuthorities());
	SecurityContextHolder.getContext().setAuthentication(newAuthentication);
	session.setAttribute("SPRING_SECURITY_CONTEXT", newAuthentication);

 

 

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.Map;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.oauth2.core.user.OAuth2User;

import kr.iei.hotel.member.dto.MemberDto;

// '/login'호출시 여기서 진행
// 로그인 완료시 시큐리티 세션 생성(Security ContextHolder)
// Authentication 타입 객체(세션에 저장될 오브젝트) -> Member정보

@SuppressWarnings("serial")	// 원래 SerialVersionUID를 선언해서 warnings를 없애야 함
public class PrincipalDetails implements UserDetails, OAuth2User {

	private MemberDto memberDto;
	private Map attributes;

	// 일반 로그인
	public PrincipalDetails(MemberDto memberDto) {
		this.memberDto = memberDto;
	}
	
	public MemberDto getMemberDto() {
		return memberDto;
	}
	
	// OAuth 로그인
	public PrincipalDetails(MemberDto memberDto, Map attributes) {
		this.memberDto = memberDto;
		this.attributes = attributes;
	}
	
	// 권한 (원래 권한이 여러개 있을 수 있으므로 Collection 루프 돌려야 함)
	@Override
	public Collection getAuthorities() {
		Collection authorities = new ArrayList<>();
//		collect.add(new GrantedAuthority() {
//			@Override
//			public String getAuthority() {
//				return memberDto.getMemberRole();	// "ROLE_" + @가 되어야 함
//			}
//		});
		authorities.add( () -> { return memberDto.getMemberRole();});
		return authorities;
	}

	// 권한 (String)
	public String getRole() {
		return memberDto.getMemberRole();
	}
	
	// 일련번호
	public Long getNumber() {
		return memberDto.getMemberNumber();
	}
	
	// 아이디
	@Override
	public String getUsername() {
		return memberDto.getMemberId();
	}

	// 이름
	@Override
	public String getName() {
		return memberDto.getMemberName();
	}
	
	// 닉네임
	public String getNick() {
		return memberDto.getMemberNick();
	}
	
	// 비밀번호
	@Override
	public String getPassword() {
		return memberDto.getMemberPassword();
	}

	// 이메일
	public String getEmail() {
		return memberDto.getMemberEmail();
	}
	
	// 등급
	public String getGrade() {
		return memberDto.getMemberGrade();
	}
	
	// 전화번호
	public String getPhone() {
		return memberDto.getMemberPhone();
	}

	// 변경 권장 기간 내 비밀번호 변경 여부
	public boolean getIsPwChanged() {
		boolean result = true;
		if (memberDto.getMemberPwChangeDate() != null) {
			Date pwChangeDate = memberDto.getMemberPwChangeDate();
			Calendar baseDate = Calendar.getInstance();
			baseDate.setTime(new Date());
			baseDate.add(Calendar.DATE, -90);
			result =  pwChangeDate.after(baseDate.getTime());
		}
		return result;	// true : 변경 불필요, false : 변경 필요
	}
	
	// 계정 만료(false) 여부
	@Override
	public boolean isAccountNonExpired() {
		return true;
	}

	// 계정 정지(false) 여부
	@Override
	public boolean isAccountNonLocked() {
		return true;
	}

	// 계정 신용(false) 여부
	@Override
	public boolean isCredentialsNonExpired() {
		return true;
	}

	// 계정 활성(false) 여부 (예 : 최종 로그인 후 일정기간 경과 여부 -> 휴면계정)
	@Override
	public boolean isEnabled() {
		return true;
	}

	@Override
	public Map getAttributes() {
		return attributes;
	}
	
}

 

 

 

 

 

about author

PHRASE

Level 60  라이트

그대의 가치는 그대가 품고 있는 이상에 의해 결정된다. 용기는 위기에 처했을 때 빛나는 힘이다. -그라시안

댓글 ( 4)

댓글 남기기

작성