I need to find those user who are logged in our application.
We are using Spring Security and there must be a way to find out users' IPs.
I think these information are stored in their sessions. In Spring Security, the current sessions are stored in SessionRegistry. From this class I can have list of authenticated users and some session information. (Using getAllPrincipals
, getAllSessions
and getSessionInformation
)
The question is, how can I have access to current users' IPs? Consider we have to give service to a known region only.
The SessionInformation is not much help as it does not contain much information.

- 5,192
- 6
- 53
- 77
-
You may find that `Authentication.getDetails()` returns a `WebAuthenticationDetails` object, which contains the remote address. – OrangeDog Apr 01 '16 at 14:16
3 Answers
I think that the check be achieved by using hasIpAddress http expression
See section 15.2 Web Security Expressions
<http use-expressions="true">
<intercept-url pattern="/admin*"
access="hasRole('admin') and hasIpAddress('192.168.1.0/24')"/>
...
</http>
If you want more flexibility, you can implement your own IP address check service, based on IpAddressMatcher:
<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 implementation:
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: you can try to get current user IP this way:
public static String getRequestRemoteAddr(){
HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes())
.getRequest();
return request.getRemoteAddr();
}
update The information about the relation between IP addresses and sessions can only be gathered from the different sources(like listening to AuthenticationSuccessEvent and SessionDestroyedEvent events, implementing a filter or using an AOP interceptor). Spring Security doesn't store such information because it's useless, as IP address has some meaning only while the server is processing a ServletRequest.
IP address may change(user may be using a proxy), so we can only audit different kinds of events like logging in with some credentials, accessing a service from a different IP, or doing some suspicious activity.

- 1
- 1

- 17,493
- 9
- 70
- 91
-
So I can have each user's IP. But the thing that I'm looking is to have a list of IPs, related to authenticated users or current sessions. Is there a way? – Matin Kh Aug 12 '12 at 09:09
-
@MatinKh I think you can subscribe to ApplicationEvents and log Spring Security session events to track active users [for example](http://static.springsource.org/spring-security/site/docs/3.0.x/apidocs/org/springframework/security/core/session/SessionDestroyedEvent.html). – Boris Treukhov Aug 12 '12 at 09:18
-
So close! But it is for destroying. Is it possible something like this, when session is being created? – Matin Kh Aug 12 '12 at 09:34
-
http://static.springsource.org/spring-security/site/docs/3.0.x/apidocs/org/springframework/security/authentication/event/InteractiveAuthenticationSuccessEvent.html – Boris Treukhov Aug 12 '12 at 09:41
-
@MatinKh `Consider we have to give service to a known region only.` please clarify your question, because available services are determined individually per IP, if you just want to see the list of IPs you can implement a classic [HttpSessionListener](http://docs.oracle.com/javaee/5/api/javax/servlet/http/HttpSessionListener.html) So you don't need to know the list of the all active users to limit access by ip – Boris Treukhov Aug 12 '12 at 09:50
-
Probably you're right. I was hoping I could find a way to find users' IPs via Spring's framework. Seems there is not such opportunity. – Matin Kh Aug 12 '12 at 10:10
-
1Trying to determine what you are looking for, I think it sounds like you want "show me all the authenticated users, as well as the last IP address they came from"? Or would it be "the IP address at the time they authenticated"? Or would it be "any IP address they used during their current session"? You can see the original question isn't entirely clear ;) - however, any solution along these lines would require you to extend the Spr Sec UserDetails object with this custom data, and then (probably) store it somewhere persistent. – Peter Mularien Sep 06 '12 at 03:41
-
What means if I get IP address of a user like this: 0:0:0:0:0:0:0:1? which obvious is wrong. – zygimantus Aug 19 '15 at 06:04
-
1@zygimantus It's ipv6 loopback address and it's perfectly reasonable if you are on the same machine. You can disable ipv6 for JRE via command line options if your app supposed to only run in ipv4 network. – Boris Treukhov Aug 19 '15 at 06:29
You can get IP address from WebAuthenticationDetails object, which can be obtained from Authentication instance.
Object details =
SecurityContextHolder.getContext().getAuthentication().getDetails();
if (details instanceof WebAuthenticationDetails)
ipAddress = ((WebAuthenticationDetails) details).getRemoteAddress();

- 20,738
- 6
- 52
- 55
You can use HttpServletRequest for getting user's IP address. (Developers of SpringSecurity do this in the same way in their expression hasIpAddress(...) that is placed in WebSecurityExpressionRoot class).
For example you can get HttpServletRequest in 2 ways:
1) Using RequestContextHolder:
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
.getRequestAttributes()).getRequest();
2) Using autowiring:
@Autowired
private HttpServletRequest request;
I took this from here.
Then using HttpServletRequest you can get Ip address in such way:
String address = request.getRemoteAddr();
And here how addresses are compared in 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));
}
And IpAddressMatcher class:
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);
}
}
}
EDIT:
According to related questions here and here you can add user's IP to the session using custom filter. And then get this information from session related to the user where it will be necessary. For example you can put user's IP info like this:
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
}
-
Look, it's good, but as I'm seeing, you are referring `SecurityContextHolder` which contains current user. So I'm deducing that I can have each user's IP using your method. However, I'm looking for a way to have all users' IPs. Is there a way? – Matin Kh Aug 12 '12 at 09:04
-
I don't think that SpringSecurity holds somewhere information about logged in user's IP. – dimas Aug 12 '12 at 15:01
-
Any idea to solve it? http://stackoverflow.com/questions/11922402/get-list-of-current-users-ips-in-web-application – Matin Kh Aug 13 '12 at 04:44