1. 程式人生 > >簡單的登錄權限驗證實現

簡單的登錄權限驗證實現

prefix void 定向 exceptio clas 攔截 登錄 scrip oca

1.登錄

登錄時需要生成一個自定義的token,token的生成規則一般可以考慮混合多種因素,如userId+生成時間+UUID,再進行一定的編碼

String token=userId+UUID.randomUUID().toString();
然後將生成的token放入session

request.getSession().setAttribute("token", token);

並將該token管理起來

public static Map<String, String> userLoginInfoMap = new ConcurrentHashMap<String, String>();

loginMap.put(session.getId(), token);

2.設置session的過期時間

在web.xml中加入

<listener> 
<listener-class>com.project.listener.SessionListener</listener-class> 
</listener>

<!-- session超時定義,單位為分鐘 -->
<session-config>
<session-timeout>1440</session-timeout> <!--1440分鐘(1天)後失效 -->
</session-config>

project自行修改為當前項目名

在session過期時清除map

package com.project.listener;

import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

public class SessionListener implements HttpSessionListener {
    //Session創建時的方法
    public void sessionCreated(HttpSessionEvent event) {
    }

    
public void sessionDestroyed(HttpSessionEvent event) { HttpSession session = event.getSession(); synchronized (this) { loginMap.remove(session.getId()); } } }

3.使用Filter過濾請求,使未登錄用戶自動跳轉到登錄頁

<!-- Filter過濾未授權用戶 -->
    <filter>
        <filter-name>LoginFilter</filter-name>
        <filter-class>com.project.filter.LoginFilter</filter-class>
        <!-- 定義Filter過濾的忽略列表 -->
        <init-param>
            <param-name>ignores</param-name>
            <param-value>/login.jsp</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>LoginFilter</filter-name>
        <url-pattern>*.jsp</url-pattern>
    </filter-mapping>

攔截所有的jsp頁面請求,這裏login.jsp登錄頁本身設置成不能被攔截

package com.project.filter;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang3.StringUtils;

public class LoginFilter extends HttpServlet implements Filter {
    private static final long serialVersionUID = 1L;

    private Set<String> prefixIignores = new HashSet<String>();

    public void doFilter(ServletRequest arg0, ServletResponse arg1,
            FilterChain arg2) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) arg0;
        HttpServletResponse response = (HttpServletResponse) arg1;
        String url = request.getRequestURI();

        // 過濾忽略列表
        for (String ignore : prefixIignores) {
            if (url.startsWith(ignore)) {
                arg2.doFilter(request, response);
                return;
            }
        }
        HttpSession session = request.getSession();
        String token = (String)session.getAttribute("token");

        if (StringUtils.isNotBlank(token) && loginMap.get(session.getId()) == token) {
            arg2.doFilter(request, response);
        } else {
            // 判斷獲取的路徑不為空且不是訪問登錄頁面或執行登錄操作時跳轉
            if (url != null && !url.equals("")
                    && (url.indexOf("Login") < 0 && url.indexOf("login") < 0)) {
                //重定向到登錄頁
                //response.sendRedirect(request.getContextPath() + "/login.jsp");
                //使用重定向無法解決在iframe中跳轉的問題,所以使用window.top.location跳轉
                response.setContentType("text/html;charset=UTF-8");
                response.setCharacterEncoding("UTF-8");// 防止彈出的信息出現亂碼
                String loginUrl="http://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath()+"/login.jsp"; //登錄頁URL
                PrintWriter out = response.getWriter();
                out.print("<script>alert(‘登錄信息已失效!‘)</script>");
                out.print(
                        "<script>window.top.location="+"\""+loginUrl+"\""+"</script>");
                out.flush();
                out.close();
            }
        }
        return;
    }

    public void init(FilterConfig config) throws ServletException {
        if (config == null) {
            return;
        }
        // 初始化忽略列表
        String cp = config.getServletContext().getContextPath();
        String ignoresParam = config.getInitParameter("ignores");
        String[] ignoreArray = ignoresParam.split(",");
        for (String s : ignoreArray) {
            prefixIignores.add(cp + s);
        }
    }
}

在filter的init-param中設置的頁面將不被攔截,加入到prefixIignores忽略列表,在doFilter攔截到的頁面先判斷是否是忽略列表,如果是的話就不攔截,不是的話再進行後續攔截,當檢測到token無效時引導用戶跳轉到登錄頁重新登錄,這裏不使用重定向的方式,因為當在iframe中進行重定向跳轉時,外部頂層頁面並不會進行跳轉。

簡單的登錄權限驗證實現