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作为唯一标识即可

原文地址:https://www.cnblogs.com/lwx521/p/10191029.html