SpringBoot Filterを使用して署名認証認証権を実現する例示的なコード
13705 ワード
情景説明
鑑権はいろいろな案があります。例えば、Spring Security、Shro、傍受、フィルターなどです。いくつかのURLだけを認証したら、私達は終わります。
Spring SecurityやShroなどのフレームを導入する必要は全くありません。スクリーンやフィルターを使って需要を実現します。
ここでは、フィルタFilterを使用してURL署名認証認証を行う方法を紹介します。
本人テストソフトハードウェア環境:Windows 10、Eclipse、Spring Boot、JDK 1.8
準備工作
第一歩:pom.xmlに関連する依存性を導入する
SpringBoot Filterを使って署名認証認証権を実現する--- 論理コード
第一歩:フィルタの作成
Servletコンポーネント(フィルタ、モニターなど)。
テストします
テストの説明
クライアントipは私達が設定したipホワイトリストにあります。 かつタイムスタンプ + secret + bodyStringMD 5暗号化されたフィールドは、要求ヘッダ領域から送られてきたsignature値と同じであり、認証が通過する。
説明:
1.ipホワイトリスト本例は、サービス端末の対応サービスのシステム構成ファイルaplication.propertiesに設定されている。
2.secretはクライアント側とサーバー側が決めたMD 5暗号化用の一つです。 セット自体は伝送しません。
3.bodyStringは、クライアントのrequestを通じてサービス先が取得した要求体のデータである。
4.signatureはクライアントが暗号化した値であり、サーバーは元のデータをクライアントと同じ暗号化するだけで、
暗号化結果と転送サービス側のsignatureを比較すると、認証が通過します。
プロジェクトを起動し、postmanを使ってテストしてください。
プログラム印刷のログを与えると、より分かりやすくなります。
ヒント:本人がテストする時、私のパソコンはサーバーでもクライアントでもあるので、そのようなipを取得しました。
注:ipまたはAuthortization値のいずれかまたは二つが条件を満たしていない場合、フロントエンド403に戻ります。
ここでは効果図は与えられません。
テストの結果から分かりました。署名認証が成功しました。
テスト項目コード委託管理リンク: https://github.com/JustryDeng/PublicRepository
ここで、SpringBootに関するFilterを使って署名認証認証権を実現するための例示的なコードについての記事を紹介します。Spring Boot Filter署名認証の内容については、以前の文章を検索したり、下記の関連記事を引き続き閲覧したりしてください。これからもよろしくお願いします。
鑑権はいろいろな案があります。例えば、Spring Security、Shro、傍受、フィルターなどです。いくつかのURLだけを認証したら、私達は終わります。
Spring SecurityやShroなどのフレームを導入する必要は全くありません。スクリーンやフィルターを使って需要を実現します。
ここでは、フィルタFilterを使用してURL署名認証認証を行う方法を紹介します。
本人テストソフトハードウェア環境:Windows 10、Eclipse、Spring Boot、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>
第二ステップ:システムプロファイルappication.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
ステップ3:クライアント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;
}
}
第四ステップ:MD 5暗号化ツール類の準備
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);
}
}
第五ステップ:簡単にControllerを作成し、後のテストに便利です。SpringBoot Filterを使って署名認証認証権を実現する--- 論理コード
第一歩:フィルタの作成
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()));
}
}
第二ステップ:プロジェクトのスタートクラスに@Servlet ComponentScan注釈を追加し、スキャンを許可するServletコンポーネント(フィルタ、モニターなど)。
テストします
テストの説明
クライアントipは私達が設定したipホワイトリストにあります。 かつタイムスタンプ + secret + bodyStringMD 5暗号化されたフィールドは、要求ヘッダ領域から送られてきたsignature値と同じであり、認証が通過する。
説明:
1.ipホワイトリスト本例は、サービス端末の対応サービスのシステム構成ファイルaplication.propertiesに設定されている。
2.secretはクライアント側とサーバー側が決めたMD 5暗号化用の一つです。 セット自体は伝送しません。
3.bodyStringは、クライアントのrequestを通じてサービス先が取得した要求体のデータである。
4.signatureはクライアントが暗号化した値であり、サーバーは元のデータをクライアントと同じ暗号化するだけで、
暗号化結果と転送サービス側のsignatureを比較すると、認証が通過します。
プロジェクトを起動し、postmanを使ってテストしてください。
プログラム印刷のログを与えると、より分かりやすくなります。
ヒント:本人がテストする時、私のパソコンはサーバーでもクライアントでもあるので、そのようなipを取得しました。
注:ipまたはAuthortization値のいずれかまたは二つが条件を満たしていない場合、フロントエンド403に戻ります。
ここでは効果図は与えられません。
テストの結果から分かりました。署名認証が成功しました。
テスト項目コード委託管理リンク: https://github.com/JustryDeng/PublicRepository
ここで、SpringBootに関するFilterを使って署名認証認証権を実現するための例示的なコードについての記事を紹介します。Spring Boot Filter署名認証の内容については、以前の文章を検索したり、下記の関連記事を引き続き閲覧したりしてください。これからもよろしくお願いします。