Spring 如何在InputerDetails服务中获取客户端IP地址
我想从ImplUserDetails类中的loadUserByUsername方法中获取客户端IP地址。这是我的代码,但它不起作用Spring 如何在InputerDetails服务中获取客户端IP地址,spring,spring-boot,spring-security,Spring,Spring Boot,Spring Security,我想从ImplUserDetails类中的loadUserByUsername方法中获取客户端IP地址。这是我的代码,但它不起作用 @Service public class LoginServiceImpl implements UserDetailsService { @Autowired UserDao loginDao; @Autowired private HttpServletRequest request; @Override public UserDetails loadU
@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){
// ...
}
}
它得到了分离:
java.lang.IllegalStateException:未找到线程绑定请求:是
您引用了实际web请求之外的请求属性,
或者在最初接收线程之外处理请求?如果
您实际上是在web请求中操作,并且仍然收到此请求
消息,您的代码可能正在外部运行
DispatcherServlet/DispatcherPortlet:在这种情况下,使用
RequestContextListener或RequestContextFilter公开当前
请求
将loadUserByUsernameString用户名更改为
loadUserByUsernameString用户名,HttpServletRequest请求
将请求从控制器端传递到服务端。像下面这样
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 autowire。有多种选项可以使@Autowired能够将HttpServletRequest注入bean: 注册RequestContextListener 注册RequestContextFilter。确保将其放置在过滤器链的最开头,例如springSecurityFilterChain之前
如果您正在使用Spring boot,并且在类路径上有一个Spring mvc,那么默认情况下,它的自动配置应该为您注册一个。它是UserDetailsService的一个实现,不能更改数字参数方法Interface中没有此覆盖更改UserDetailsService接口中的方法定义。然后可以在LoginServiceImpl类中重写。另一方面,HttpServletRequest是一个web内容。您可以在应用程序web交互时获得这些信息。因此,它必须从控制器端或拦截器传递。如果他更改接口方法定义,他必须每次手动执行登录,并且不能使用spring security的自动登录筛选器。检查此问题