アプリケーションにログインしているユーザーを見つける必要があります。
私たちはSpringSecurityを使用しており、ユーザーのIPを見つける方法が必要です。
これらの情報は彼らのセッションに保存されていると思います。Spring Securityでは、現在のセッションはSessionRegistryに保存されます。このクラスから、認証されたユーザーのリストといくつかのセッション情報を取得できます。(、、およびを使用getAllPrincipals
)getAllSessions
問題getSessionInformation
は
、現在のユーザーのIPにどのようにアクセスできるかということです。既知の地域にのみサービスを提供する必要があると考えてください。SessionInformation
には多く
の情報が含まれていないため、あまり役に立ちません。
3 に答える
hasIpAddress http 式を使用することでチェックが達成されると思います
セクション15.2 Web セキュリティ式を参照してください。
<http use-expressions="true">
<intercept-url pattern="/admin*"
access="hasRole('admin') and hasIpAddress('192.168.1.0/24')"/>
...
</http>
さらに柔軟性が必要な場合は、IpAddressMatcher に基づいて独自の IP アドレス チェック サービスを実装できます。
<bean id="ipCheckService" class="my.IpCheckService">
</bean>
<security:http auto-config="false" access-denied-page="/accessDenied.jsp"
use-expressions="true">
<security:intercept-url pattern="/login.jsp"
access="@ipCheckService.isValid(request)" />
Bean の実装:
public class IpCheckService {
public boolean isValid(HttpServletRequest request) {
//This service is a bean so you can inject other dependencies,
//for example load the white list of IPs from the database
IpAddressMatcher matcher = new IpAddressMatcher("192.168.1.0/24");
try {
return matcher.matches(request);
} catch (UnsupportedOperationException e) {
return false;
}
}
}
update : 次の方法で現在のユーザー IP を取得できます。
public static String getRequestRemoteAddr(){
HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes())
.getRequest();
return request.getRemoteAddr();
}
更新IP アドレスとセッション間の関係に関する情報は、さまざまなソース (AuthenticationSuccessEvent および SessionDestroyedEvent イベントのリッスン、フィルターの実装、AOP インターセプターの使用など) からのみ収集できます。Spring Security は、サーバーがServletRequestを処理している間のみ IP アドレスが何らかの意味を持つため、役に立たないため、そのような情報を保存しません。
IP アドレスは変更される可能性があるため (ユーザーがプロキシを使用している可能性があります)、資格情報を使用したログイン、別の IP からのサービスへのアクセス、疑わしいアクティビティの実行など、さまざまな種類のイベントのみを監査できます。
ユーザーの IP アドレスを取得するには、HttpServletRequest を使用できます。(SpringSecurity の開発者は、 WebSecurityExpressionRootクラスに配置される式hasIpAddress(...)で同じ方法でこれを行います)。
たとえば、次の 2 つの方法で HttpServletRequest を取得できます。
1) RequestContextHolder の使用:
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
.getRequestAttributes()).getRequest();
2) 自動配線の使用:
@Autowired
private HttpServletRequest request;
ここから 取った.
次に、HttpServletRequestを使用して、次の方法で IP アドレスを取得できます。
String address = request.getRemoteAddr();
そして、Spring Security でアドレスを比較する方法は次のとおりです。
/**
* Takes a specific IP address or a range using the IP/Netmask (e.g. 192.168.1.0/24 or 202.24.0.0/14).
*
* @param ipAddress the address or range of addresses from which the request must come.
* @return true if the IP address of the current request is in the required range.
*/
public boolean hasIpAddress(String ipAddress) {
return (new IpAddressMatcher(ipAddress).matches(request));
}
そして IpAddressMatcher クラス:
public final class IpAddressMatcher implements RequestMatcher {
private final int nMaskBits;
private final InetAddress requiredAddress;
/**
* Takes a specific IP address or a range specified using the
* IP/Netmask (e.g. 192.168.1.0/24 or 202.24.0.0/14).
*
* @param ipAddress the address or range of addresses from which the request must come.
*/
public IpAddressMatcher(String ipAddress) {
if (ipAddress.indexOf('/') > 0) {
String[] addressAndMask = StringUtils.split(ipAddress, "/");
ipAddress = addressAndMask[0];
nMaskBits = Integer.parseInt(addressAndMask[1]);
} else {
nMaskBits = -1;
}
requiredAddress = parseAddress(ipAddress);
}
public boolean matches(HttpServletRequest request) {
return matches(request.getRemoteAddr());
}
public boolean matches(String address) {
InetAddress remoteAddress = parseAddress(address);
if (!requiredAddress.getClass().equals(remoteAddress.getClass())) {
return false;
}
if (nMaskBits < 0) {
return remoteAddress.equals(requiredAddress);
}
byte[] remAddr = remoteAddress.getAddress();
byte[] reqAddr = requiredAddress.getAddress();
int oddBits = nMaskBits % 8;
int nMaskBytes = nMaskBits/8 + (oddBits == 0 ? 0 : 1);
byte[] mask = new byte[nMaskBytes];
Arrays.fill(mask, 0, oddBits == 0 ? mask.length : mask.length - 1, (byte)0xFF);
if (oddBits != 0) {
int finalByte = (1 << oddBits) - 1;
finalByte <<= 8-oddBits;
mask[mask.length - 1] = (byte) finalByte;
}
// System.out.println("Mask is " + new sun.misc.HexDumpEncoder().encode(mask));
for (int i=0; i < mask.length; i++) {
if ((remAddr[i] & mask[i]) != (reqAddr[i] & mask[i])) {
return false;
}
}
return true;
}
private InetAddress parseAddress(String address) {
try {
return InetAddress.getByName(address);
} catch (UnknownHostException e) {
throw new IllegalArgumentException("Failed to parse address" + address, e);
}
}
}
編集:
関連する質問hereおよびhereに従って、カスタム フィルターを使用してユーザーの IP をセッションに追加できます。そして、必要なユーザーに関連するセッションからこの情報を取得します。たとえば、次のようにユーザーの IP 情報を入力できます。
public class MonitoringFilter extends GenericFilterBean{
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
String userIp = httpRequest.getRemoteAddr();
httpRequest.getSession().setAttribute("userIp", userIp);
// Add other attributes to session if necessary
}