纳税服务系统五(登陆与系统拦截)【配置系统、子系统首页、登陆与拦截】(下)

简介: 到目前位置,我们的用户模块和角色模块基本已经做好了,我们的纳税服务系统是放在一个大系统里边的。我们应该把我们已经写好的模块加载进去。 本文主要的知识点: 配置系统首页 登陆模块 权限拦截模块


处理首页


当用户访问首页的时候,我们重定向到登陆页面:

  • 访问Index页面的时候,我们就重定向到登陆页面上。


<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
  String path = request.getContextPath();
  String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
  response.sendRedirect(basePath + "sys/login_loginUI.action");
%>

过滤器模块


进入系统拦截


我们讲道理是要用户登陆后,才能访问我们的总系统。但是现在假如用户知道了我们的首页地址,他可以直接访问我们的首页地址而不用登陆。这是不合适的。

12.jpg



因此,我们写一个过滤器进行拦截,如果用户不是想要登陆,而访问我们其他的页面。都拦截他,让他登陆后才能访问。


13.jpg


这里写图片描述

过滤器:


package zhongfucheng.core.filter;
import zhongfucheng.user.entity.User;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
 * Created by ozc on 2017/6/4.
 */
public class LoginFilter implements Filter {
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        //得到用户访问的路径
        String uri = request.getRequestURI();
        //登陆路径
        String loginPath = request.getContextPath() + "/sys/login_login.action";
        //判断用户访问的是哪里
        if (!uri.contains("login_")) {//如果不是访问我们的登陆模块
            //判断该用户是否登陆了。
            User user = (User) request.getSession().getAttribute("SYS_USER");
            if (user == null) {//如果在session找不到,那么就是没有登陆
                //没有登陆,跳转到登陆页面
                response.sendRedirect(loginPath);
                return;
            } else {//有用户信息,就是登陆了。
                //放行
                chain.doFilter(request, response);
            }
        } else {//如果是访问我们的登陆模块,放行
            chain.doFilter(request, response);
        }
    }
    public void init(FilterConfig config) throws ServletException {
    }
    public void destroy() {
    }
}


配置过滤器,需要在struts过滤器之前配置:


<filter>
        <filter-name>LoginFilter</filter-name>
        <filter-class>zhongfucheng.core.filter.LoginFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>LoginFilter</filter-name>
        <url-pattern>*.action</url-pattern>
    </filter-mapping>



权限过滤


我们的纳税服务子系统并不是任何人都可以进去操作的,我们有可以对角色的管理,对用户的管理。。一般的用户是没有权限去操作这些东西的。因此,我们要对其进行权限控制。

当该用户有权限才能够访问纳税服务系统的内容,没有权限就不给该用户看。

权限过滤的前提条件:

  • 用户已经登陆了
  • 知道用户访问的是什么子系统

由于我们在LoginFilter中已经可以得到这两个条件了,于是我们在LoginFilter中接着写就行了。又因为权限过滤是一个比较单独的模块,我们可以将其抽出。这样一来,LoginFilter又不会显得太大,职责又分工了。

14.jpg

这里写图片描述

过滤器全部代码:WebApplicationContextUtils得到IOC中的对象

package zhongfucheng.core.filter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import zhongfucheng.core.utils.PermissionCheck;
import zhongfucheng.user.entity.User;
import zhongfucheng.user.service.UserService;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
 * Created by ozc on 2017/6/4.
 */
public class LoginFilter implements Filter {
    //注入userService
    @Autowired
    private UserService userServiceImpl;
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        //得到用户访问的路径
        String uri = request.getRequestURI();
        //登陆路径
        String loginPath = request.getContextPath() + "/sys/login_login.action";
        //提示页面
        String warningPath = request.getContextPath() + "/sys/login_noPermissionUI.action";
        //定义User变量
        User user;
        //判断用户访问的是哪里
        if (!uri.contains("login_")) {//如果不是访问我们的登陆模块
            //判断该用户是否登陆了。
             user = (User) request.getSession().getAttribute("SYS_USER");
            if (user == null) {//如果在session找不到,那么就是没有登陆
                //没有登陆,跳转到登陆页面
                response.sendRedirect(loginPath);
                return;
            } else {//有用户信息,就是登陆了。
                if (uri.contains("nsfw")) {//如果访问纳税服务系统,就要有对应的权限
                    //用户已经登陆了,判断用户有没有权限访问子系统
                    //得到IOC容器中的对象
                    WebApplicationContext applicationContext = WebApplicationContextUtils.getWebApplicationContext(request.getSession().getServletContext());
                    PermissionCheck permissionCheck = (PermissionCheck)applicationContext.getBean("permissionCheck");
                    if (permissionCheck.check(user, "nsfw")) {//有权限
                        //放行
                        chain.doFilter(request, response);
                    } else {//没有权限
                        //返回到提示页面
                        response.sendRedirect(warningPath);
                    }
                } else {//可以不用权限,直接放行
                    //放行
                    chain.doFilter(request, response);
                }
            }
        } else {//如果是访问我们的登陆模块,放行
            chain.doFilter(request, response);
        }
    }
    public void init(FilterConfig config) throws ServletException {
    }
    public void destroy() {
    }
}

在登陆完之后,就查询出用户拥有的所有角色,并设置到该用户中:

public String login() {
        if (user != null) {
            List<User> list = userServiceImpl.findUserByAccountAndPassword(user.getAccount(), user.getPassword());
            //如果查到有值,那么就证明有该用户的,给他登陆
            if (list != null && list.size() > 0) {
                //查出用户所有的权限,设置到User中
                User user = list.get(0);
                List<UserRole> roles = userServiceImpl.findRoleById(user.getId());
                user.setUserRoles(roles);
                //保存到Session域中,为了更方便用,我们使用常量保存。
                ActionContext.getContext().getSession().put(Constant.USER, user);
                //保存到日志文件中Log
                Log log = LogFactory.getLog(getClass());
                log.info("用户名称为" + list.get(0).getName() + "登陆了系统!");
                //重定向到首页
                return "home";
            } else {
                //登陆失败,记载登陆信息
                loginResult = "登陆失败了,用户名或密码错误了";
            }
        }
        //只要不成功的,都回到登陆页面
        return loginUI();
    }


在User.java中加入一个List集合,存储着用户所拥有的角色


//得到用户所有的角色
    private List<UserRole> userRoles;
    public List<UserRole> getUserRoles() {
        return userRoles;
    }
    public void setUserRoles(List<UserRole> userRoles) {
        this.userRoles = userRoles;
    }


到这里,有同学可能会疑问,为啥现在我要修改User的结构呢??明明在编写User和Role的时候说好不修改User类的。我们在验证的时候需要得到用户所有的角色,从而得到权限。如果在检查的时候做的话,我们用的是过滤器检查,每请求一次都要去访问数据库。

这样的话就非常耗费我们的性能,于是我们就修改User类,但这次的修改没有影响到我们其他地方的操作。这样一来,我们在检查的时候就可以通过对象来得到用户对应的权限了,不用查询数据库。

检查用户是否有权限:


public class PermissionCheck {
    private User user;
    private String code;
    @Autowired
    private UserService userServiceImpl;
    public boolean check(User user, String code) {
        this.user = user;
        this.code = code;
        //得到该用户的所有权限
        List<UserRole> userRoles = user.getUserRoles();
        if (userRoles == null) {
            userRoles = userServiceImpl.findRoleById(user.getId());
        }
        //遍历初用户拥有的角色,看看有没有对应的权限
        for (UserRole userRole : userRoles) {
            Role role = userRole.getUserRoleId().getRole();
            //得到角色所拥有的权限
            Set<RolePrivilege> rolePrivilegeSet = role.getRolePrivilegeSet();
            //遍历权限,看看有没有nsfw的权限
            for (RolePrivilege privilege : rolePrivilegeSet) {
                String code1 = privilege.getCompositeKey().getCode();
                if (code1.equals(code)) {//如果该用户有权限
                    return true;
                }
            }
        }
        //遍历完都没有return true,那么就是没有权限了。
        return false;
    }
}


页面嵌套问题


现在我打开了两个首页,是同一个会话的。如果用户太久没有操作我们的页面,那么Session就会被摧毁。


15.jpg


这里写图片描述

等用户再操作的时候,Session已经被Tomcat摧毁了。讲道理用户操作页面的时候,是会回到登陆页面的。我们看看发生了什么:


16.jpg


这里写图片描述

登陆页面嵌套在我们右边的显示页面了。为啥出现这种情况??

  • 当用户的Session没有了,用户操作时,过滤器就会将页面跳转到登陆页面
  • 而我们点击了左边的菜单栏,默认在右边显示

所以,到目前为止,我们的逻辑是没毛病的。但怎么解决上面遇到的情况呢??** 我们不需要使用监听器Session,监听Session被摧毁了,然后刷新页面**。。我们用更好地一种解决办法:

  • 判断自身页面是否为顶级窗口,如果不是就自动刷新父窗口的地址,跳转到顶级窗口中。


/*如果该页面不是顶级窗口,那么就自动刷新一下到父窗口中*/
    if(window!=window.parent) {
        window.parent.location.reload(true);
    }

总结

  • 对于登陆和注销功能就没什么好说的,我们已经写过很多次了。在登陆的时候就是将我们的User对象保存Session域对象中而已。
  • 当用户访问index页面的时候,我们就让它重定向到登陆页面上
  • 只有登陆了才能访问我们的系统首页,因此我们编写了一个过滤器。判断该用户是否是要访问我们的登陆页面,如果不是,就判断该用户是否登陆了(也就是判断session有没有User值)。如果有就放行,如果没有就跳转到登陆页面上
  • 我们还可以对其进行权限认证,权限认证是基于用户已经登陆的前提下的。对于权限我们直接使用权限的Code来进行校验。为了方便我们去验证,我们在登陆的时候就把用户的权限全都加载到用户上(这样的话,在每次验证就不用重复去找数据库要数据了。)
  • session失效的问题导致了页面的嵌套。我们无需监听Session失效的问题,直接在javaScript用代码判断该页面是否是顶级页面,如果不是顶级页面,直接就跳转到顶级页面就行了!
目录
相关文章
|
2月前
|
缓存 前端开发 Go
从4开始,在后端系统中增加用户注册和登录功能
从4开始,在后端系统中增加用户注册和登录功能
21 0
|
6月前
|
存储 前端开发 PHP
构建一个简单的网站,包括用户注册、登录功能
构建一个简单的网站,包括用户注册、登录功能
68 1
|
3月前
|
监控 JavaScript 应用服务中间件
匿名用户访问的接口或者无登录态场景下接口防刷的解决方案
匿名用户访问的接口或者无登录态场景下接口防刷的解决方案
41 0
|
7月前
JavaWeb用户信息管理系统-用户只能在一处登录
JavaWeb用户信息管理系统-用户只能在一处登录
28 0
|
4月前
|
SQL 监控 数据库连接
实现基于内网管理监控软件的用户身份验证系统的PHP代码详解
随着信息技术的不断发展,内网管理监控软件的需求也日益增长。为了确保系统的安全性,用户身份验证成为了至关重要的一环。本文将详细介绍如何通过PHP代码实现基于内网管理监控软件的用户身份验证系统,并提供一些代码示例。
230 0
|
7月前
|
测试技术
Fiddler如何越权访问登录成功的页面?一文讲清
Fiddler如何越权访问登录成功的页面?一文讲清
105 0
|
11月前
|
存储 JSON 前端开发
基于Springboot外卖系统04:后台系统用户登录+登出功能
如果前端与后台接口之间不存在跨域问题,那么推荐使用cookie和session来记录登录状态。如果前端与服务器接口之间存在跨域问题,那么就要使用token的方式来维持登录状态。
188 0
|
11月前
|
前端开发 Java 测试技术
基于Springboot外卖系统05:用户非登陆状态的页面拦截器实现
用户访问接口验证,如果用户没有登录,则不让他访问除登录外的任何接口。
91 0
|
前端开发 开发者 微服务
后台系统登录改造和跨域 | 学习笔记
快速学习后台系统登录改造和跨域
95 0
后台系统登录改造和跨域 | 学习笔记
|
小程序 API 数据库
小程序中实现用户的登录与注册
小程序中实现用户的登录与注册
小程序中实现用户的登录与注册