如何在 ImpUserDetailsService 中获取客户端 IP 地址
Posted
技术标签:
【中文标题】如何在 ImpUserDetailsService 中获取客户端 IP 地址【英文标题】:How to get client IP address in ImpUserDetailsService 【发布时间】:2019-10-05 10:18:50 【问题描述】:我想从 implUserDetailsService 类的 loadUserByUsername() 方法中获取客户端 IP 地址,这是我的代码,但它不起作用
@Service
public class LoginServiceImpl implements UserDetailsService
@Autowired
UserDao loginDao;
@Autowired
private HttpServletRequest request;
@Override
public UserDetails loadUserByUsername(String username)
try
final String ip = getClientIp(request);
net.liyan.psc.main.entity.main.User user = loginDao.findByUserNameForLogin(username);
if (user == null) throw new UsernameNotFoundException("User not found.");
Set<GrantedAuthority> grantedAuthorities = new HashSet<>();
if (isLocalZone())
grantedAuthorities.add(new SimpleGrantedAuthority('ROLE_1'));
else
grantedAuthorities.add(new SimpleGrantedAuthority('ROLE_2'));
return new org.springframework.security.core.userdetails.User(
user.getUsername(),
user.getPassword(),
true,
true,
true,
true,
grantedAuthorities);
catch (UsernameNotFoundException ex)
throw new UsernameNotFoundException("User not found.");
catch (Exception ex)
throw new UsernameNotFoundException("User not found.");
private static String getClientIp(HttpServletRequest request)
String remoteAddr = "";
if (request != null)
remoteAddr = request.getHeader("X-FORWARDED-FOR");
if (remoteAddr == null || "".equals(remoteAddr))
remoteAddr = request.getRemoteAddr();
return remoteAddr;
private boolean isLocalZone(String Ip)
// ...
它得到exseption:
java.lang.IllegalStateException:未找到线程绑定请求:是 您指的是实际 Web 请求之外的请求属性, 或在原始接收线程之外处理请求?如果 你实际上是在一个网络请求中操作并且仍然收到这个 消息,您的代码可能在 DispatcherServlet/DispatcherPortlet:在这种情况下,使用 RequestContextListener 或 RequestContextFilter 暴露当前 请求。
【问题讨论】:
看看这个问题***.com/questions/36736861/… 【参考方案1】:有多种选择可以让@Autowired
能够将HttpServletRequest
注入到一个bean 中:
-
注册
RequestContextListener
注册RequestContextFilter
。确保它位于过滤器链的最开头(例如,在springSecurityFilterChain
之前)
如果你使用 Spring boot 并且在 classpath 上有一个 spring-mvc,它的自动配置应该默认为你注册一个 RequestContextFilter。
【讨论】:
【参考方案2】:把loadUserByUsername(String username)
改成
loadUserByUsername(String username, HttpServletRequest request)
将请求从控制器端传递到您的服务端。像下面这样,
import javax.servlet.http.HttpServletRequest;
@Controller
public class YourControllerName
@Autowired
UserDetailsService userDetailsService
@GetMapping("/your-url")
public String methodName(HttpServletRequest request /*your other perams*/)
UserDetails userDetails = userDetailsService .loadUserByUsername(String
username, request);
//other operations
return "view";
从服务端移除 HttpServletRequest 自动装配。
【讨论】:
它是UserDetailsService的一个实现,不能改变数字参数方法接口中没有这个Override 更改 UserDetailsService 接口中的方法定义。然后,您可以在 LoginServiceImpl 类中覆盖。另一方面,HttpServletRequest 是一个 Web 内容。您会在应用程序 Web 交互时获得此信息。所以它必须从控制器端或拦截器传递。 如果更改接口方法定义,每次都必须手动登录,不能使用spring security的自动登录过滤器。以上是关于如何在 ImpUserDetailsService 中获取客户端 IP 地址的主要内容,如果未能解决你的问题,请参考以下文章
春季 Oauth2。 DaoAuthenticationProvider 中未设置密码编码器