如何在 ImpUserDetailsS​​ervice 中获取客户端 IP 地址

Posted

技术标签:

【中文标题】如何在 ImpUserDetailsS​​ervice 中获取客户端 IP 地址【英文标题】:How to get client IP address in ImpUserDetailsService 【发布时间】:2019-10-05 10:18:50 【问题描述】:

我想从 implUserDetailsS​​ervice 类的 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 自动装配。

【讨论】:

它是UserDetailsS​​ervice的一个实现,不能改变数字参数方法接口中没有这个Override 更改 UserDetailsS​​ervice 接口中的方法定义。然后,您可以在 LoginServiceImpl 类中覆盖。另一方面,HttpServletRequest 是一个 Web 内容。您会在应用程序 Web 交互时获得此信息。所以它必须从控制器端或拦截器传递。 如果更改接口方法定义,每次都必须手动登录,不能使用spring security的自动登录过滤器。

以上是关于如何在 ImpUserDetailsS​​ervice 中获取客户端 IP 地址的主要内容,如果未能解决你的问题,请参考以下文章

Quickblox 位置示例不起作用

unistd.h文件

CentOS 7安装Docker

春季 Oauth2。 DaoAuthenticationProvider 中未设置密码编码器

DynamoDB 中分区和排序键查询的渐近性能是不是为常数 O(1)?

如何在图像中找到明亮区域(以及如何在图像中找到阴影区域)