Struts2 interceptor login verification

Struts2 Interceptor

The concept of Struts2 interceptors is the same as Spring Mvc interceptors.

  1. Struts2 interceptor is to implement interception before or after accessing an Action or a certain method or field of Action, and Struts2 interceptor is pluggable, and the interceptor is an implementation of AOP.
  2. Interceptor Stack. The Struts2 interceptor stack is to link the interceptors into a chain in a certain order. When accessing an intercepted method or field, the interceptors in the Struts2 interceptor chain are called in the order in which they were previously defined.

The first step of using the interceptor:

Customize my permission interceptor CheckPrivilegeInterceptor. This interceptor inherits from the abstract class AbstractInterceptor. Of course, you can implement the interface of Interceptor.

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import com.shizongger.oa.domain.User;

public class CheckPrivilegeInterceptor extends AbstractInterceptor {

    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
        System.out.println("---拦截器未拦截之前---");
        String result = invocation.invoke();
        System.out.println("---拦截器拦截之后---");
        return result;
    }
}

The custom interceptor should override the abstract method intercept() method of the AbstractInterceptor abstract class. This method intercepts all actions. The return value of String type is the view we will return. If we want to release the action address we want to intercept, Then the code is as shown above.

Second step using interceptor:

Configure the struts configuration file, mainly to configure the custom interceptor and configure the interceptor stack. Add the following configuration under the package element node of the struts.xml configuration file:

<!-- 配置拦截器 -->
        <interceptors>
            <!-- 声明拦截器 -->
            <interceptor name="checkPrivilege" class="com.shizongger.oa.util.CheckPrivilegeInterceptor"></interceptor>

            <!-- 重新定义默认的拦截器栈 -->
            <interceptor-stack name="defaultStack">
                <interceptor-ref name="checkPrivilege"></interceptor-ref>           
                <interceptor-ref name="defaultStack"></interceptor-ref>             
            </interceptor-stack>
        </interceptors>

Start my Tomcat server, when I enter my action address in the browser, it will be intercepted by the interceptor's intercept. The default is to let go. If an empty string is returned, an error will be reported because the corresponding view cannot be found.

Login and Permission Blocking

The most common application scenarios of interceptors in web development are login verification and permission verification. For those users who are not logged in to the system, we generally send all his requests back to the login page. And for those users who have logged in to the system, if you do not have the appropriate permissions, then you will not be able to access our url.

First, some systems in the listener do some monitoring tasks.

public class MyServletContextListener implements ServletContextListener {

    Log log = LogFactory.getLog(this.getClass());

    @Autowired
    private PrivilegeService privilegeService;

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        log.debug("---销毁监听器---");
    }

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        ServletContext sc = sce.getServletContext();
        ApplicationContext ac = WebApplicationContextUtils.getWebApplicationContext(sc);
        PrivilegeService privilegeService = (PrivilegeService) ac.getBean("privilegeServiceImpl");
        List<Privilege> topPrivilegeList = privilegeService.findTopList();
        //将权限list放到比application作用域还大的ServletContext
        sc.setAttribute("topPrivilegeList", topPrivilegeList);

        // 准备数据:allPrivilegeUrls
        Collection<String> allPrivilegeUrls = privilegeService.getAllPrivilegeUrls();
        sc.setAttribute("allPrivilegeUrls", allPrivilegeUrls);      
    }
}

The task of the listener is to obtain Spring's container ApplicationContext from the Web container, and then obtain the permission service class privilegeService from the ApplicationContext. This service has two main functions. One is to obtain a list of multiple top-level permissions; the other is to obtain all permissions. list. Put these two into the application.

Next, we can write the logic code for login interception in our interceptor.

    public String intercept(ActionInvocation invocation) throws Exception {     
        //获取信息,从session中取出当前登录用户
        User user = (User) ActionContext.getContext().getSession().get("user");
        String nameSpace = invocation.getProxy().getNamespace();
        String actionName = invocation.getProxy().getActionName();
        //对应的权限地址
        String privilegeUrl = nameSpace + actionName;

        //如果未登录
        if(user == null) {
            //如果是去登录的页面和登录请求,就放行
            if("/user_login".equals(privilegeUrl)) {
                return invocation.invoke();
            //否则跳转到登录页面
            } else {
                return "loginUI";
            }
        } else {
            //如果已经登录则判断是否有权限
            if(user.hasPrivilegeByUrl(privilegeUrl)) {
                return invocation.invoke();
            } else {
                return "noPrivilegeError";
            }
        }
    }

The logic of the processing is that if the user is not logged in, it is determined whether to log in. If the user is logging in, it is released, and other requests must jump to the loginUI login page. If already logged in, determine whether the user who is logging in has the corresponding authority. And the method of judging whether it has permission is in my user.java.

/**
 * 用户实体
 * @author shizongger
 * @date 2017/03/24
 */
public class User {
    private Log log = LogFactory.getLog(this.getClass());

    private Long id;

    private String loginName;

    private String password;

    private String name;

    private String gender;

    private String phoneNumber;

    private String email;

    private String description;

    private Department department;

    private Set<Role> roles;

    //getter/settter方法

    /**
     * 判断用户是否用该权限
     * @param privilegename 权限名称
     * @return
     */
    public boolean hasPrivilegeByName(String privilegeName) {
        log.debug("权限名称:" + privilegeName);

        //从本用户中取出所有角色
        for(Role role : roles) {
            //从角色遍历出所有权限
            Set<Privilege> privilegeList = role.getPrivileges();
            for(Privilege privilege : privilegeList) {
                if(privilegeName.equals(privilege.getName())) {
                    log.debug(privilegeName + "---有权限---");
                    return true;
                }
            }
        }

        log.debug(privilegeName + "---没有权限---");
        return false;
    }

    /**
     * 判断本用户是否有指定URL的权限
     * 
     * @param privUrl
     * @return
     */
    public boolean hasPrivilegeByUrl(String privUrl) {
        // 超级管理有所有的权限
        if (isAdmin()) {
            return true;
        }

        // >> 去掉后面的参数
        int pos = privUrl.indexOf("?");
        if (pos > -1) {
            privUrl = privUrl.substring(0, pos);
        }
        // >> 去掉UI后缀
        if (privUrl.endsWith("UI")) {
            privUrl = privUrl.substring(0, privUrl.length() - 2);
        }

        // 如果本URL不需要控制,则登录用户就可以使用
        Collection<String> allPrivilegeUrls = (Collection<String>) ActionContext.getContext().getApplication().get("allPrivilegeUrls");
        if (!allPrivilegeUrls.contains(privUrl)) {
            return true;
        } else {
            // 普通用户要判断是否含有这个权限
            for (Role role : roles) {
                for (Privilege priv : role.getPrivileges()) {
                    if (privUrl.equals(priv.getUrl())) {
                        return true;
                    }
                }
            }
            return false;
        }
    }

    /**
     * 判断本用户是否是超级管理员
     * 
     * @return
     */ 
    public boolean isAdmin() {
        return "admin".equals(loginName);
    }
}

The hasPrivilegeByUrl() method is the code logic for judging whether the user has permission according to the url. This logic is divided into three parts. First, if the logged-in user is the super administrator admin, there is no need to verify the authority, and the user has all the authority. Second, if the basic functions of the logged-in user do not need to be verified, only the functions that require verification require verification. Basic function modules such as home page, logout, login page, etc. are not to be verified again.

The service implementation class for permissions is as follows:

@Service
public class PrivilegeServiceImpl extends DaoSupportImpl<Privilege> implements PrivilegeService {

    @Override
    @Transactional
    public List<Privilege> findTopList() {
        List<Privilege> topPrivletList = this.getSession()
        .createQuery("FROM Privilege p WHERE p.parent IS NULL")
        .list();

        return topPrivletList;
    }

    @Override
    @Transactional
    public Collection<String> getAllPrivilegeUrls() {
        return getSession().createQuery(//
                "SELECT DISTINCT p.url FROM Privilege p WHERE p.url IS NOT NULL")//
                .list();
    }

}

If you are not logged in, directly enter the main page and it will automatically return to the login page, as shown in the figure
Visit the main page without logging in

The permissions in the login state are as follows:
Permissions after login

Also:
1. Spring Mvc interceptor, please refer to spring mvc interceptor
2. The GitHub address of this project

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325975745&siteId=291194637