博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
纳税服务系统九【登陆、权限拦截、页面嵌套】
阅读量:6162 次
发布时间:2019-06-21

本文共 11313 字,大约阅读时间需要 37 分钟。


tags: 纳税服务系统项目


前言

到目前为止,我们已经写了用户模块和角色模块了。也已经把系统的首页和子系统的首页配置好了。我们的系统是需要登陆后才能访问的

因此,本博文主要讲解登陆模块、权限拦截


登陆模块

编写Action与配置文件

引入对应的JSP页面

编写Action处理请求和对应的配置文件:

效果:

Action处理

在常量类中保存着一个Session的标识:

/***********保存Session域的常量***********/    public static String USER = "SYS_USER";复制代码

Action

package zhongfucheng.login;import com.opensymphony.xwork2.ActionContext;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.springframework.beans.factory.annotation.Autowired;import zhongfucheng.core.action.BaseAction;import zhongfucheng.core.constant.Constant;import zhongfucheng.user.entity.User;import zhongfucheng.user.service.UserService;import java.util.List;/** * Created by ozc on 2017/6/2. */public class LoginAction extends BaseAction {    /***************封装数据**********************/    private User user;    public User getUser() {        return user;    }    public void setUser(User user) {        this.user = user;    }    /****************调用userService****************************/    @Autowired    private UserService userServiceImpl;    public String loginUI() {        return "loginUI";    }    /****************记载着登陆状态信息*********************/    private String loginResult;    public String getLoginResult() {        return loginResult;    }    public void setLoginResult(String loginResult) {        this.loginResult = loginResult;    }    /*****************业务方法******************/    public String login() {        if (user != null) {            List
list = userServiceImpl.findUserByAccountAndPassword(user.getAccount(), user.getPassword()); //如果查到有值,那么就证明有该用户的,给他登陆 if (list != null && list.size() > 0) { //保存到Session域中,为了更方便用,我们使用常量保存。 ActionContext.getContext().getSession().put(Constant.USER, list.get(0)); //保存到日志文件中Log Log log = LogFactory.getLog(getClass()); log.info("用户名称为" + list.get(0).getName() + "登陆了系统!"); //重定向到首页 return "home"; } else { //登陆失败,记载登陆信息 loginResult = "登陆失败了,用户名或密码错误了"; } } //只要不成功的,都回到登陆页面 return loginUI(); }}复制代码

在dao层中实现根据账户和密码查询数据:

@Override    public List
findUserByAccountAndPassword(String account, String password) { //通过账户和密码查找对象 String sql = "FROM User WHERE account=? AND password=?"; return getSession().createQuery(sql).setParameter(0, account).setParameter(1,password).list(); }复制代码

我们还在Action中定义了一个String来记载着Login的状态,如果出错了。我们就返回loginUI界面,然后在那里回显Login出错的信息。

  • 效果:

同时登录完在系统主页上回显数据:

欢迎您,
 
复制代码


注销功能

在主页上的退出上绑定超链接

退出复制代码

Action处理:

public String logout() {                //销毁session的值        ActionContext.getContext().getSession().remove(Constant.USER);                return loginUI();    }复制代码

处理首页

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

  • 访问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");%>复制代码

过滤器模块

进入系统拦截

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

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

过滤器:

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过滤器之前配置:

LoginFilter
zhongfucheng.core.filter.LoginFilter
LoginFilter
*.action
复制代码

效果:


权限过滤

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

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

权限过滤的前提条件:

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

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

过滤器全部代码: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
list = userServiceImpl.findUserByAccountAndPassword(user.getAccount(), user.getPassword()); //如果查到有值,那么就证明有该用户的,给他登陆 if (list != null && list.size() > 0) { //查出用户所有的权限,设置到User中 User user = list.get(0); List
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
userRoles; public List
getUserRoles() { return userRoles; } public void setUserRoles(List
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
userRoles = user.getUserRoles(); if (userRoles == null) { userRoles = userServiceImpl.findRoleById(user.getId()); } //遍历初用户拥有的角色,看看有没有对应的权限 for (UserRole userRole : userRoles) { Role role = userRole.getUserRoleId().getRole(); //得到角色所拥有的权限 Set
rolePrivilegeSet = role.getRolePrivilegeSet(); //遍历权限,看看有没有nsfw的权限 for (RolePrivilege privilege : rolePrivilegeSet) { String code1 = privilege.getCompositeKey().getCode(); if (code1.equals(code)) {
//如果该用户有权限 return true; } } } //遍历完都没有return true,那么就是没有权限了。 return false; }}复制代码

页面嵌套问题

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

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

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

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

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

  • 判断自身页面是否为顶级窗口,如果不是就自动刷新父窗口的地址,跳转到顶级窗口中。
/*如果该页面不是顶级窗口,那么就自动刷新一下到父窗口中*/	if(window!=window.parent) {	    window.parent.location.reload(true);	}复制代码

总结

  • 对于登陆和注销功能就没什么好说的,我们已经写过很多次了。在登陆的时候就是将我们的User对象保存Session域对象中而已。
  • 当用户访问index页面的时候,我们就让它重定向到登陆页面上
  • 只有登陆了才能访问我们的系统首页,因此我们编写了一个过滤器。判断该用户是否是要访问我们的登陆页面,如果不是,就判断该用户是否登陆了(也就是判断session有没有User值)。如果有就放行,如果没有就跳转到登陆页面上
  • 我们还可以对其进行权限认证,权限认证是基于用户已经登陆的前提下的。对于权限我们直接使用权限的Code来进行校验。为了方便我们去验证,我们在登陆的时候就把用户的权限全都加载到用户上(这样的话,在每次验证就不用重复去找数据库要数据了。)
  • session失效的问题导致了页面的嵌套。我们无需监听Session失效的问题,直接在javaScript用代码判断该页面是否是顶级页面,如果不是顶级页面,直接就跳转到顶级页面就行了!

如果您觉得这篇文章帮助到了您,可以给作者一点鼓励

转载地址:http://ohefa.baihongyu.com/

你可能感兴趣的文章
Codeforces Round #431 (Div. 1)
查看>>
如何进行数组去重
查看>>
将标题空格替换为 '_' , 并自动复制到剪切板上
查看>>
List Collections sort
查看>>
Mysql -- You can't specify target table 'address' for update in FROM clause
查看>>
使用局部标准差实现图像的局部对比度增强算法。
查看>>
2017-2018-1 20165313 《信息安全系统设计基础》第八周学习总结
查看>>
《代码敲不队》第四次作业:项目需求调研与分析
查看>>
菜鸡互啄队—— 团队合作
查看>>
HttpWebRequest的GetResponse或GetRequestStream偶尔超时 + 总结各种超时死掉的可能和相应的解决办法...
查看>>
SparseArray
查看>>
第二章
查看>>
android背景选择器selector用法汇总
查看>>
[转]Paul Adams:为社交设计
查看>>
showdialog弹出窗口刷新问题
查看>>
java
查看>>
Vue.js连接后台数据jsp页面  ̄▽ ̄
查看>>
关于程序的单元测试
查看>>
mysql内存优化
查看>>
都市求生日记第一篇
查看>>