SpringBoot 는 Filter 를 사용 하여 서명 인증 인증 권한 을 실현 하 는 예시 코드

상황 설명
        감 권,많은 방안 이 있 습 니 다.예 를 들 어 SpringSecurity,Shiro,차단기,필터 등 이 있 습 니 다.일부 URL 에 대한 인증 인증 인증 만 한다 면 저 희 는 끝 냅 니 다.
SpringSecurity 나 Shiro 등 프레임 워 크 를 도입 할 필요 가 없고 차단기 나 필 터 를 사용 하면 수 요 를 충족 시 킬 수 있다.
        본 고 는 필터 필 터 를 사용 하여 URL 서명 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증
본인 테스트 소프트 하드웨어 환경:Windows 10,Eclipse,SpringBoot,JDK 1.8
준비 작업
 첫 번 째 단계:pom.xml 에 관련 의존 도 를 도입 합 니 다.

<dependencies>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter</artifactId>
	</dependency>
 
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-test</artifactId>
		<scope>test</scope>
	</dependency>
 
	<!-- web -->
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-web</artifactId>
	</dependency>
 
	<!-- devtools -->
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-devtools</artifactId>
	</dependency>
 
	<!-- org.apache.commons.codec -->
	<!-- MD5      -->
	<dependency>
		<groupId>org.apache.directory.studio</groupId>
		<artifactId>org.apache.commons.codec</artifactId>
		<version>1.8</version>
	</dependency>
</dependencies>
두 번 째 단계:시스템 프로필 application.properties 에 관련 매개 변 수 를 설정 합 니 다.잠시 후 코드 에 사용 해 야 합 니 다.

# ip   (        )
permitted-ips = 169.254.205.177, 169.254.133.33, 10.8.109.31, 0:0:0:0:0:0:0:1
# secret
secret = JustryDeng
세 번 째 단계:클 라 이언 트 IP 를 가 져 올 도구 클래스 준비

import java.net.InetAddress;
import java.net.UnknownHostException;
 
import javax.servlet.http.HttpServletRequest;
 
/**
 *     request      ip
 *  :          ,         ip
 *    https://blog.csdn.net/byy8023/article/details/80499038
 * 
 *     :
 *           ,          ip  ;      ip  (d       VMware ,       );
 *             [    \    Internet\    ]           
 *
 * @author JustryDeng
 * @DATE 2018 9 10    8:56:48
 */
public class IpUtil {
	
    public static String getIpAddr(HttpServletRequest request) {
        String ipAddress = null;
        try {
            ipAddress = request.getHeader("x-forwarded-for");
            if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getHeader("Proxy-Client-IP");
            }
            if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getHeader("WL-Proxy-Client-IP");
            }
            if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getRemoteAddr();
                if (ipAddress.equals("127.0.0.1")) {
                    //           IP
                    InetAddress inet = null;
                    try {
                        inet = InetAddress.getLocalHost();
                    } catch (UnknownHostException e) {
                        e.printStackTrace();
                    }
                    ipAddress = inet.getHostAddress();
                }
            }
            //            ,   IP      IP,  IP  ','  
            if (ipAddress != null && ipAddress.length() > 15) { // "***.***.***.***".length()
                                                                // = 15
                if (ipAddress.indexOf(",") > 0) {
                    ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
                }
            }
        } catch (Exception e) {
            ipAddress="";
        }
        
        return ipAddress;
    }
}
STEP 4:MD5 암호 화 도구 클래스 준비

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import org.apache.commons.codec.binary.Hex;
 
/**
 * MD5     
 *
 * @author JustryDeng    ShaoJJ MD5       
 * @DATE 2018 9 11    2:14:21
 */
public class MDUtils {
 
	/**
	 *   
	 *
	 * @param origin
	 *                    
	 * @param charsetname
	 *                , UTF-8
	 * @DATE 2018 9 11    2:12:51
	 */
	public static String MD5EncodeForHex(String origin, String charsetname) 
			throws UnsupportedEncodingException, NoSuchAlgorithmException {
		return MD5EncodeForHex(origin.getBytes(charsetname));
	}
 
	public static String MD5EncodeForHex(byte[] origin) throws NoSuchAlgorithmException {
		return Hex.encodeHexString(digest("MD5", origin));
	}
 
	/**
	 *       
	 *
	 * @throws NoSuchAlgorithmException
	 * @DATE 2018 9 11    2:11:58
	 */
	private static byte[] digest(String algorithm, byte[] source) throws NoSuchAlgorithmException {
		MessageDigest md;
		md = MessageDigest.getInstance(algorithm);
		return md.digest(source);
	}
}
다섯 번 째 단계:컨트롤 러 를 간단하게 작성 하여 뒤의 테스트 를 편리 하 게 합 니 다.

  SpringBoot 필터 로 서명 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 논리 코드
첫 번 째 단계:필터 작성

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
 
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ReadListener;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
 
import com.aspire.util.IpUtil;
import com.aspire.util.MDUtils;
 
/**
 * SpringBoot           (  )
 * @WebFilter         URL
 *   URL          ,     @Order(x)     request     ,x        
 * 
 * @author JustryDeng
 * @DATE 2018 9 11    1:18:29
 */
@WebFilter(urlPatterns = { "/authen/test1", "/authen/test2", "/authen/test3"})
public class SignAutheFilter implements Filter {
 
	private static Logger logger = LoggerFactory.getLogger(SignAutheFilter.class);
 
	@Value("${permitted-ips}")
	private String[] permittedIps;
 
	@Value("${secret}")
	private String secret;
	
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
	}
 
	@Override
	public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
			throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) res;
		try {
			String authorization = request.getHeader("Authorization");
			logger.info("getted Authorization is ---> " + authorization);
			String[] info = authorization.split(",");
 
			//      ip
			String ip = IpUtil.getIpAddr(request);
			logger.info("getted ip is ---> " + ip);
			
			/* 
			 *          (     )
			 *  :            ;               ,  @RequestBody        
			 *            getReader() has already been called for this request
			 *     :                     .        ,            ,   .
			 *                     ,             .
			 *              HttpServletRequestWrapper    
			 *       :          、   ;
			 */
			MyRequestWrapper mrw = new MyRequestWrapper(request);
			String bodyString = mrw.getBody();
			logger.info("getted requestbody data is ---> " + bodyString);
			
			//          
			//   authorization   
			// cardid="1234554321",timestamp="9897969594",signature="a69eae32a0ec746d5f6bf9bf9771ae36"
			//    ,          
			int cardidIndex = info[0].indexOf("=") + 2;
			String cardid = info[0].substring(cardidIndex, info[0].length() - 1);
			logger.info("cardid is ---> " + cardid);
			int timestampIndex = info[1].indexOf("=") + 2;
			String timestamp = info[1].substring(timestampIndex, info[1].length() - 1);
			int signatureIndex = info[2].indexOf("=") + 2;
			String signature = info[2].substring(signatureIndex, info[2].length() - 1);
			String tmptString = MDUtils.MD5EncodeForHex(timestamp + secret + bodyString, "UTF-8")
					                .toUpperCase();
			logger.info("getted ciphertext is ---> {}, correct ciphertext is ---> {}", 
					       signature , tmptString);
 
			//    ip    
			boolean containIp = false;
			for (String string : permittedIps) {
				if (string.equals(ip)) {
					containIp = true;
					break;
				}
			}
 
			//    Authorization      ,          
			boolean couldPass = containIp && tmptString.equals(signature);
			if (couldPass) {
				//   
				chain.doFilter(mrw, response);
				return;
			}
			response.sendError(403, "Forbidden");
		} catch (Exception e) {
			logger.error("AxbAuthenticationFilter -> " + e.getMessage(), e);
			response.sendError(403, "Forbidden");
		}
	}
 
	@Override
	public void destroy() {
 
	}
 
}
 
/**
 *     --->           (  )       
 *
 * @author JustryDeng
 * @DATE 2018 9 11    7:13:52
 */
class MyRequestWrapper extends HttpServletRequestWrapper {
 
    private final String body;
 
    public String getBody() {
		return body;
	}
 
	public MyRequestWrapper(final HttpServletRequest request) throws IOException {
        super(request);
        StringBuilder sb = new StringBuilder();
        String line;
        BufferedReader reader = request.getReader();
        while ((line = reader.readLine()) != null) {
            sb.append(line);
        }
 
        body = sb.toString();
    }
 
    @Override
    public ServletInputStream getInputStream() throws IOException {
        final ByteArrayInputStream bais = new ByteArrayInputStream(body.getBytes());
        return new ServletInputStream() {
            /*
             *   ServletInputStream   InputStream   
             */
            @Override
            public int read() throws IOException {
                return bais.read();
            }
            
			@Override
			public boolean isFinished() {
				return false;
			}
 
			@Override
			public boolean isReady() {
				return false;
			}
 
			@Override
			public void setReadListener(ReadListener listener) {	
			}
        };
    }
 
    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(this.getInputStream()));
    }
}
두 번 째 단계:프로젝트 의 시작 클래스 에@ServletComponentscan 주 해 를 추가 하여 스 캔 을 허용 합 니 다.
            Servlet 구성 요소(필터,모니터 등).

테스트 해 봐.
테스트 설명
    클 라 이언 트 ip 는 우리 가 설정 한 ip 화이트 리스트 에 있 습 니 다. 타임 스탬프 + secret + body StringMD 5 암호 화 된 필드 는 요청 헤드 필드 에서 전 달 된 signature 값 과 동시에 감 권 이 통 과 됩 니 다.
설명:
        1.ip 화이트 리스트 본 예제 에 서 는 서버 의 해당 서비스 에 설 치 된 시스템 프로필 application.properties 에 설 치 된 것 입 니 다.
        2.secret 는 클 라 이언 트 측 과 서버 측 이 정 한 MD5 암호 화 에 사용 되 는 것 입 니 다.  수,시 크 릿 자 체 는 전송 하지 않 습 니 다.
        3.bodyString 은 서버 에서 클 라 이언 트 의 request 를 통 해 얻 은 요청 체 의 데이터 입 니 다.
        4.signature 는 클 라 이언 트 가 암호 화 된 값 입 니 다.서버 는 원본 데 이 터 를 클 라 이언 트 와 똑 같이 암호 화하 기만 하면 됩 니 다.
           암호 화 결 과 를 서버 의 signature 와 비교 하면 인증 권 이 통 과 됩 니 다.
프로젝트 시작,post man 으로 테스트 해 보기

프로그램 인쇄 로 그 를 보 내 면 이해 하기 쉽 습 니 다.

알림:본인 이 테스트 할 때 제 컴퓨터 는 서버 이자 클 라 이언 트 이기 때문에 그런 ip 을 얻 었 습 니 다.
주:ip 또는 Authorization 값 중 하나 또는 두 개가 조건 을 만족 시 키 지 못 할 경우 전단 403(SignAuthoseFilter 의 관련 코드 참조)으로 되 돌아 갑 니 다.
     여 기 는 효과 도 를 제시 하지 않 겠 습 니 다.
테스트 결과 에서 알 수 있 듯 이 서명 감 권 성공!
테스트 항목 코드 위탁 관리 링크:  https://github.com/JustryDeng/PublicRepository ​
SpringBoot 가 Filter 를 사용 하여 서명 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증 인증

좋은 웹페이지 즐겨찾기