最近公司的網站需要添加用戶訪問記錄功能,由於使用了nginx請求轉發直接通過HttpServletRequest無法獲取用戶真實Ip
關於nginx獲取真實IP的資料 https://blog.csdn.net/bigtree_3721/article/details/72820081
獲取用戶真實IP具體做法:
在nginx.conf配置文件中
location / {
proxy_pass ip;
index ak47.html index.html index.htm;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# 動態請求的轉發
location ~ \.(jsp|do)$ {
proxy_pass http://10.30.100.126:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
然后在代碼中加入以下
public final class NetworkUtil {
public static String getIpAddr(HttpServletRequest request) {
String fromSource = "X-Real-IP";
String ip = request.getHeader("X-Real-IP");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("X-Forwarded-For");
fromSource = "X-Forwarded-For";
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
fromSource = "Proxy-Client-IP";
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
fromSource = "WL-Proxy-Client-IP";
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
fromSource = "request.getRemoteAddr";
}
return ip;
}
}
用戶登錄時間和退出時間
用戶登錄時間就是subject.login(token);成功的時間
退出時間就是執行logout的時間,但是shiro封裝的很完美,怎么在執行logout之后往數據庫中插入退出時間呢
shiro執行logout時會調用LogoutFilter,我們可以寫一個繼承它就可以進行相關操作了
@Component
public class SystemLogoutFilter extends LogoutFilter {
@Override
protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
//在這里執行退出系統前需要清空的數據
Subject subject=getSubject(request,response);
//Session session = subject.getSession();
String redirectUrl=getRedirectUrl(request,response,subject);
ServletContext context= request.getServletContext();
try {
subject.logout();
context.removeAttribute("error");
}catch (SessionException e){
e.printStackTrace();
}
issueRedirect(request,response,redirectUrl);
return false;
}
}
然后在xml配置文件中
<!--Spring整合shiro--> <bean id="SystemLogoutFilter" class="com.smart.service.SystemLogoutFilter"> <property name="redirectUrl" value="/login.do" /> </bean> <!-- 配置shiro的過濾器工廠類,id- shiroFilter要和我們在web.xml中配置的過濾器一致 --> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <!-- 調用我們配置的權限管理器 --> <property name="securityManager" ref="securityManager" /> <!-- 配置我們的登錄請求地址 --> <property name="loginUrl" value="/login.do" /> <!-- 配置我們在登錄頁登錄成功后的跳轉地址,如果你訪問的是非/login地址,則跳到您訪問的地址 --> <property name="successUrl" value="/maSystem.do" /> <!-- 如果您請求的資源不再您的權限范圍,則跳轉到/403請求地址 --> <property name="unauthorizedUrl" value="/error.do" /> <property name="filters"> <map> <entry key="logout" value-ref="SystemLogoutFilter" /> </map> </property> <!-- 權限配置 --> <property name="filterChainDefinitions"> <value> <!-- anon表示此地址不需要任何權限即可訪問 --> /error.jsp=anon /login.do=anon /logout=logout <!--所有的請求(除去配置的靜態資源請求或請求地址為anon的請求)都要通過登錄驗證,如果未登錄則跳到/login --> /** = authc </value> </property> </bean> <bean id="logoutFilter" class="org.apache.shiro.web.filter.authc.LogoutFilter"> <property name="redirectUrl" value="/login.do" /> </bean>
用戶退出登錄時間都有了,根據sessionId作為唯一標識即可