SpringSecurity 를 사용 하여 사용자 정의 Token 검 사 를 진행 합 니 다.

배경
Spring Security 는 기본적으로'사용자 이름/비밀번호'방식 으로 로그 인 검 사 를 하고 쿠키 를 통 해 로그 인 정 보 를 저장 합 니 다.일부 맞 춤 형 장면,예 를 들 어 token 문자열 을 단독으로 사용 하여 일부 페이지 의 접근 권한 을 제어 하려 고 할 때 기본 방안 은 지원 되 지 않 습 니 다.
인터넷 에서 관련 실천 을 검색 하지 못 한 상황 에서 공식 문서 와 개별 Stack Overflow 의 분산 사례 를 통 해 전체적인 방향 을 형성 하고 테스트 를 통 과 했 습 니 다.본 고 는 이 방안 에 대한 공유 입 니 다.
참조
SpringSecurity 검사 절차
기본 적 인 SpringSecurity 사용 방식 은 인터넷 에 많 기 때문에 본 고의 중점 이 아니다.
검사 의 전체 절차 에 대해 간단하게 말하자면 전체 링크 는 세 가지 관건 이 있다.
  • 감정 권 이 필요 한 클래스/방법/url)을 감정 권 이 필요 한 것 으로 정의 합 니 다(본 고 는 코드 예 시 를 방법 상 주석@PreAuthorize("hasPermission('ARGET','PERMISSION')")
  • 방문 한 정보 에 따라 방문 자의 권한 정보 Authentication 을 만 들 고 문맥 에 삽입 합 니 다
  • 감 권 방법 을 호출 할 때 지 정 된 감 권 방식 에 따라 권한 정보 가 권한 요구 에 부합 되 는 지 검증 합 니 다
  • 완전한 호출 체인 은 IDE 에서 단일 디 버 깅 을 통 해 직접 체험 하고 본 고 는 관련 정 리 를 하지 않 는 것 을 권장 합 니 다.
    사용자 정의
    사용자 정의 token 을 사용 하여 권한 을 검증 하 는 것 이 필요 합 니 다.
  • Authentication 을 생 성하 고 상하 문 에 삽입 합 니 다
  • token 에 대한 검증 방식
    해 야 할 일 은 다음 과 같다.
  • TokenAuthentication 클래스 를 사용자 정의 하여 org.springframework.security.core.Authenticaion 을 실현 하고 token 권한 정보 로 서
  • AuthenticationTokenFilter 클래스 를 사용자 정의 하여 javax.servlet.Filter 를 실현 합 니 다.방문 을 받 았 을 때 방문 정보 에 따라 TokenAuthentication 인 스 턴 스 를 생 성하 고 컨 텍스트 를 삽입 합 니 다
  • 사용자 정의 Security Permission Evalutor 클래스,org.springframework.security.access.Permission Evaluator 를 실현 하고 권한 의 사용자 정의 검증 논 리 를 완성 합 니 다
  • 전체 설정 에서 Security Permission Evalutor 를 권한 검사 방식 으로 정의 합 니 다TokenAuthentication.java
    
    /**
     * @author: Blaketairan
     */
    import org.springframework.security.core.Authentication;
    import org.springframework.security.core.GrantedAuthority;
    import java.util.ArrayList;
    import java.util.Collection;
    /**
     * Description: spring-security Authentication      (    token)
     */
    public class TokenAuthentication implements Authentication{
        private String token;
        public TokenAuthentication(String token){
            this.token = token;
        }
        @Override
        public Collection<? extends GrantedAuthority> getAuthorities() {
            return new ArrayList<GrantedAuthority>(0);
        }
        @Override
        public Object getCredentials(){
            return token;
        }
        @Override
        public Object getDetails() {
            return null;
        }
        @Override
        public Object getPrincipal() {
            return null;
        }
        @Override
        public boolean isAuthenticated() {
            return true;
        }
        @Override
        public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
        }
        @Override
        public String getName() {
            return null;
        }
    }
    AuthenticationTokenFilter.java
    
    /**
     * @author: Blaketairan
     */
    import com.google.common.base.Strings;
    import com.blaketairan.spring.security.configuration.TokenAuthentication;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.core.Authentication;
    import org.springframework.security.core.context.SecurityContextHolder;
    import javax.servlet.*;
    import javax.servlet.http.HttpServletRequest;
    import java.io.IOException;
    /**
     * Description:        token  spring-security        Authenticaion  
     */
    @Configuration
    public class AuthenticationTokenFilter implements Filter{
        @Override
        public void init(FilterConfig filterConfig) throws ServletException{
        }
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,FilterChain filterChain)
                throws IOException, ServletException{
            if (servletRequest instanceof HttpServletRequest){
                String token = ((HttpServletRequest) servletRequest).getHeader("PRIVATE-TOKEN");
                if (!Strings.isNullOrEmpty(token)){
                    Authentication authentication = new TokenAuthentication(token);
                    SecurityContextHolder.getContext().setAuthentication(authentication);
                    System.out.println("Set authentication with non-empty token");
                } else {
                    /**
                     *     Token ,     TokenAuthenticaion  ,    SpringSecurity          
                     */
                    Authentication authentication = new TokenAuthentication("");
                    SecurityContextHolder.getContext().setAuthentication(authentication);
                    System.out.println("Set authentication with empty token");
                }
            }
            filterChain.doFilter(servletRequest, servletResponse);
        }
        @Override
        public void destroy(){
        }
    }
    
    SecurityPermissionEvalutor.java
    
    /**
     * @author: Blaketairan
     */
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.security.access.PermissionEvaluator;
    import org.springframework.security.core.Authentication;
    import java.io.Serializable;
    /**
     * Description: spring-security           (  )
     */
    public class SecurityPermissionEvaluator implements PermissionEvaluator {
        @Override
        public boolean hasPermission(Authentication authentication,Object targetDomainObject, Object permission){
            String targetDomainObjectString = null;
            String permissionString = null;
            String token = null;
            try {
                targetDomainObjectString = (String)targetDomainObject;
                permissionString = (String)permission;
                token = (String)authentication.getCredentials();
            } catch (ClassCastException e){
                e.printStackTrace();
                return false;
            }
            return hasPermission(token, targetDomainObjectString, permissionString);
        }
        @Override
        public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission){
            /**
             *   @PreAuthorize("hasPermission('TARGET','PERMISSION')")  ,        
             */
            return false;
        }
        private boolean hasPermission(String token,String targetDomain, String permission){
            /**
             *     
            **/
            return true;
        }
    }
    
    SecurityConfig.java 전역 설정
    
    /**
     * @author: Blaketairan
     */
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.access.PermissionEvaluator;
    import org.springframework.security.authentication.AuthenticationManager;
    import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    /**
     * Description: spring-security  ,              
     */
    @Configuration
    @EnableWebSecurity
    @EnableGlobalMethodSecurity(prePostEnabled = true)
    public class SecurityConfig extends WebSecurityConfigurerAdapter{
        @Bean
        @Override
        protected AuthenticationManager authenticationManager() throws Exception{
            return super.authenticationManager();
        }
        @Bean
        public PermissionEvaluator permissionEvaluator() {
            /**
             *           
            **/
            SecurityPermissionEvaluator securityPermissionEvaluator = new SecurityPermissionEvaluator();
            return securityPermissionEvaluator;
        }
        @Override
        protected void configure(HttpSecurity httpSecurity) throws Exception{
            /**
             *   csrf    ip    
            **/
            httpSecurity
                    .csrf()
                    .disable()
                    .httpBasic()
                    .disable();
        }
    }
    
    BaseRepository.java 권한 검증 이 필요 한 방법
    
    /**
     * @author: Blaketairan
     */
    import org.springframework.security.access.prepost.PreAuthorize;
    import java.util.List;
    /**
     * Description: 
     */
    public interface BaseRepository{
        @PreAuthorize("hasPermission('DOMAIN', 'PERMISSION')")
        void deleteAll();
    }
    
    spring security 사용자 정의 token 프레임 워 크 인증 을 통과 할 수 없습니다.
    코드 와 같이 token 과 refreshToken 을 사용자 정의 합 니 다.
    
    UserDO userDO = userMapper.getByName(username);
    UserDetails userDetails = 
    userService.loadUserByUsername(userForBase.getName());
    String token = jwtTokenComponent.generateToken(userDO);
    String refreshToken = jwtTokenComponent.generateRefreshToken(userDO);
    storeToken(userDO, token,refreshToken);
    jsonObject.put("principal", userDetails);
    jsonObject.put("token_type", "bearer");
    return jsonObject;
    프레임 워 크 인증 을 통과 할 수 없 습 니까?그것 을 하 다
    
    UserDO userDO = userMapper.getByName(username);
    UserDetails userDetails = 
    userService.loadUserByUsername(userForBase.getName());
    String token = jwtTokenComponent.generateToken(userDO);
    String refreshToken = jwtTokenComponent.generateRefreshToken(userDO);
    storeToken(userDO, token,refreshToken);
    jsonObject.put("access_token", token);
    jsonObject.put("refresh_token", refreshToken);
    jsonObject.put("principal", userDetails);
    jsonObject.put("token_type", "bearer");
    return jsonObject;
    
    private void storeToken(UserDO userDO, String token,String refreshToken) {
            Map<String, String> tokenParams = new HashMap<>();
            tokenParams.put("access_token", token);
            tokenParams.put("expires_in", "7200");
            tokenParams.put("token_type", "bearer");
            OAuth2AccessToken oAuth2AccessToken = DefaultOAuth2AccessToken.valueOf(tokenParams);
            DefaultOAuth2RefreshToken oAuth2RefreshToken = new DefaultOAuth2RefreshToken(refreshToken);
            //   redisTemplate,     
            Map<String, String> requestMap = new HashMap<>();
            requestMap.put("username", userDO.getUsername());
            requestMap.put("grant_type", "password");
            Map<String, Object> queryMap = new HashMap<String, Object>();
            queryMap.put("id",userDO.getUserId());
            List<String> perms = menuMapper.listUserPerms(queryMap);
            Set<GrantedAuthority> authorities = new HashSet<>();
            for (String perm : perms) {
    if (StringUtils.isNotBlank(perm)) {
        authorities.add(new SimpleGrantedAuthority(perm.trim()));
    }
            }
            OAuth2Request storedRequest = new OAuth2Request(requestMap, "oms-web", authorities, true, null,
        null, null, null, null);
            CustomUserDetails userEnhancer = new CustomUserDetails(userDO, true, true, true, true, authorities);
            UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userEnhancer, null, userEnhancer.getAuthorities());
            authentication.setDetails(requestMap);
            OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(storedRequest, authentication);
            tokenStore.storeAccessToken(oAuth2AccessToken, oAuth2Authentication);
            tokenStore.storeRefreshToken(oAuth2RefreshToken, oAuth2Authentication);
        }
    이상 은 개인 적 인 경험 이 므 로 여러분 에 게 참고 가 되 기 를 바 랍 니 다.여러분 들 도 저 희 를 많이 응원 해 주시 기 바 랍 니 다.

    좋은 웹페이지 즐겨찾기