Mat*_* Kh 11 ip session spring spring-security
我需要找到那些登录我们的应用程序的用户.
我们正在使用Spring Security,必须有办法找出用户的IP.
我认为这些信息存储在他们的会话中.在Spring Security中,当前会话存储在SessionRegistry中.从这个类我可以有经过身份验证的用户列表和一些会话信息.(使用getAllPrincipals
,getAllSessions
和getSessionInformation
)
的问题是,我怎么能有机会获得当前用户的IP地址?考虑我们必须仅为已知区域提供服务.
该SessionInformation没有太大的帮助,因为它并不包含太多的信息.
Bor*_*hov 17
我认为通过使用hasIpAddress http表达式来实现检查
<http use-expressions="true">
<intercept-url pattern="/admin*"
access="hasRole('admin') and hasIpAddress('192.168.1.0/24')"/>
...
</http>
Run Code Online (Sandbox Code Playgroud)
如果您想要更多灵活性,可以基于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)" />
Run Code Online (Sandbox Code Playgroud)
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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
更新:您可以尝试以这种方式获取当前用户IP:
public static String getRequestRemoteAddr(){
HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes())
.getRequest();
return request.getRemoteAddr();
}
Run Code Online (Sandbox Code Playgroud)
更新有关IP地址和会话之间关系的信息只能从不同的源收集(例如,监听AuthenticationSuccessEvent和SessionDestroyedEvent事件,实现过滤器或使用AOP拦截器).Spring Security不存储此类信息,因为它没用,因为IP地址仅在服务器处理ServletRequest时才有意义.
IP地址可能会更改(用户可能正在使用代理),因此我们只能审核不同类型的事件,例如使用某些凭据登录,从其他IP访问服务或执行某些可疑活动.
您可以从WebAuthenticationDetails对象获取IP地址,该对象可以从Authentication实例获取。
Object details =
SecurityContextHolder.getContext().getAuthentication().getDetails();
if (details instanceof WebAuthenticationDetails)
ipAddress = ((WebAuthenticationDetails) details).getRemoteAddress();
Run Code Online (Sandbox Code Playgroud)
您可以使用HttpServletRequest获取用户的IP地址。(SpringSecurity的开发人员以与放置在WebSecurityExpressionRoot类中的表达式hasIpAddress(...)相同的方式执行此操作)。
例如,您可以通过两种方式获取HttpServletRequest:
1)使用RequestContextHolder:
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
.getRequestAttributes()).getRequest();
Run Code Online (Sandbox Code Playgroud)
2)使用自动装配:
@Autowired
private HttpServletRequest request;
Run Code Online (Sandbox Code Playgroud)
我从这里拿来的。
然后使用HttpServletRequest您可以通过以下方式获取IP地址:
String address = request.getRemoteAddr();
Run Code Online (Sandbox Code Playgroud)
这里是如何在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));
}
Run Code Online (Sandbox Code Playgroud)
和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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:
根据此处和此处的相关问题,您可以使用自定义过滤器将用户的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
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
16565 次 |
最近记录: |