1. 程式人生 > >Spring整合shiro+nginx 實現訪問記錄

Spring整合shiro+nginx 實現訪問記錄

最近公司的網站需要新增使用者訪問記錄功能,由於使用了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作為唯一標識即可