SSH项目--国税(四)

来源:互联网 发布:漫画美图软件 编辑:程序博客网 时间:2024/04/28 11:16
6.3用户角色说明
一个用户可以对应多个角色,一个角色可以对应多个用户。用户与角色的关系也是多对多的关系。在页面中应该体现出在添加、编辑用户时可以选择多个角色;并且用户不直接关联系统的权限,用户的权限都是通过角色来关联实现。
6.4改造用户管理
6.4.1用户表实体类、映射文件的改造
新增“用户角色”实体及映射文件:
《hibernate-mapping》
《class name="cn.itcast.nsfw.user.entity.UserRole"table="user_role"》
《composite-id name="id"class="cn.itcast.nsfw.user.entity.UserRoleId"》
《key-many-to-one name="role" lazy="false"class="cn.itcast.nsfw.role.entity.Role"》
《column name="role_id"》《/column》
《/key-many-to-one》
《key-property name="userId" type="java.lang.String"》
《column name="user_id" length="32"》《/column》
《/key-property》
《/composite-id》
《/class》

《/hibernate-mapping》

6.4.2用户保存、更新、删除方法改造
1、UserAction:
在跳转到addUI时应该初始化系统的所有角色列表提供添加页面进行选择:
//跳转到新增页面
public String addUI(){
//加载角色列表
ActionContext.getContext().getContextMap().put("roleList",roleService.findObjects());
return "addUI";
}
//保存新增
public String add(){
try {
if(user != null){
//处理头像
if(headImg != null){
//1、保存头像到upload/user
//获取保存路径的绝对地址
String filePath =ServletActionContext.getServletContext().getRealPath("upload/user");
String fileName = UUID.randomUUID().toString().replaceAll("-","") +headImgFileName.substring(headImgFileName.lastIndexOf("."));
//复制文件
FileUtils.copyFile(headImg, new File(filePath,fileName));
//2、设置用户头像路径
user.setHeadImg("user/" + fileName);
}
userService.saveUserAndRole(user,userRoleIds);
}
} catch (Exception e) {
e.printStackTrace();
}
return "list";
}

更新方法:
//保存编辑
public String edit(){
try {
if(user != null){
//处理头像
if(headImg != null){
//1、保存头像到upload/user
//获取保存路径的绝对地址
String filePath =ServletActionContext.getServletContext().getRealPath("upload/user");
String fileName = UUID.randomUUID().toString().replaceAll("-","") +headImgFileName.substring(headImgFileName.lastIndexOf("."));
//复制文件
FileUtils.copyFile(headImg, new File(filePath,fileName));
//2、设置用户头像路径
user.setHeadImg("user/" + fileName);
}

userService.updateUserAndRole(user,userRoleIds);
}
} catch (Exception e) {
e.printStackTrace();
}
return "list";
}


在UserDaoImpl中:
@Override
public void saveUserRole(UserRole userRole) {
getHibernateTemplate().save(userRole);
}

@Override 
public void deleteUserRoleByUserId(Serializable id) {
Query query = getSession().createQuery("DELETE FROM UserRoleWHERE id.userId=?");
query.setParameter(0, id);
query.executeUpdate();
}

@Override
public List《UserRole》 getUserRolesByUserId(String id) {
Query query = getSession().createQuery("FROM UserRole WHEREid.userId=?");
query.setParameter(0, id);
return query.list();
}

UserServiceImpl类中:
@Override
public void delete(Serializable id) {
userDao.delete(id);
//删除用户对应的所有权限
userDao.deleteUserRoleByUserId(id);
}

@Override
public void saveUserAndRole(User user, String... roleIds){
//保存用户
save(user);
//保存用户对应角色
if(roleIds != null){
for(String roleId: roleIds){
userDao.saveUserRole(new UserRole(new UserRoleId(newRole(roleId), user.getId())));
}
}
}

@Override
public void updateUserAndRole(User user, String... roleIds){
//1、根据用户删除该用户的所有角色
userDao.deleteUserRoleByUserId(user.getId());
//2、更新用户
update(user);
//3、保存用户对应的角色
if(roleIds != null){
for(String roleId: roleIds){
userDao.saveUserRole(new UserRole(new UserRoleId(newRole(roleId), user.getId())));
}
}
}

@Override
public List《UserRole》 getUserRolesByUserId(String id) {
return userDao.getUserRolesByUserId(id);
}

2、在jsp页面中将角色选择改造为多选:
       《tr》
           《tdclass="tdBg" width="200px"》角色:《/td》
           《td》
          《s:checkboxlist list="#roleList" name="userRoleIds"listKey="roleId" listValue="name"》《/s:checkboxlist》
          《/td》
       《/tr》

7权限验证
7.1系统首页

1、编写首页cn.itcast.home.HomeAction
类的内容就一个跳转到首页的方法:
public class HomeAction extends ActionSupport {
//系统首页
public String execute(){
return "home";
}
}

2、配置home-struts.xml文件

《struts》
《package name="home" namespace="/sys"extends="struts-default"》
《action name="home_*" class="cn.itcast.home.action.HomeAction"method="{1}"》
《result name="home"》/WEB-INF/jsp/home/home.jsp《/result》
《result name="{1}"》/WEB-INF/jsp/home/{1}.jsp《/result》
《/action》
《/package》
《/struts》

将home-struts.xml加入到struts.xml中

将home.jsp 加入到项目的WEB-INF/jsp/home目录下,修改进入纳税服务首页的链接。

7.2纳税服务首页
新增纳税服务的首页对应的cn.itcast.nsfw.home.action.HomeAction,里面就只包含3个方法,分别定向frame.jsp、top.jsp、left.jsp的方法:
public class HomeAction extends BaseAction{

//跳转到纳税访问系统首页
public String frame(){
return "frame";
}
//跳转到纳税访问系统首页-顶部
public String top(){
return "top";
}
//跳转到纳税访问系统首页-左边菜单
public String left(){
return "left";
}
}



配置home-struts.xml 并包含到struts.xml中。 

之后引入welcome.jsp、bg.jsp到common目录下,frame.jsp、top.jsp、left.jsp三个jsp文件到WEB-INF/jsp/nsfw目录下并修改这3个页面中的链接和相关信息。

7.3登录与注销
7.3.1登录与注销
7.3.1.1 编写LoginAction
在这个action中;主要处理登录和注销操作;方法应该包括:
1、跳转到登录页;toLoginUI()——loginUI
2、当没有权限时,跳转到没有权限的提示页面;toNoPermissionUI()——noPermissionUI
3、登录方法;验证登录。需要具体的userService,userDao方法。

userDaoImpl类中具体的实现方法为:
@Override
public List《User》 findUsersByAcccountAndPass(String account,String password) {
Query query = getSession().createQuery("FROM User WHEREaccount=? AND password=?");
query.setParameter(0, account);
query.setParameter(1, password);
return query.list();
}



4、注销登录;logout()——tologinUI

LoginAction类:
@Resource
private UserService userService;
private User user;
private String loginResult;
//跳转到登录页面
public String toLoginUI(){
return "loginUI";
}
//登录
public String login(){
if(user != null){
if(StringUtils.isNotBlank(user.getAccount()) &&StringUtils.isNotBlank(user.getPassword()) ){
//根据用户的帐号和密码查询用户列表
List《User》 list =userService.findUserByAccountAndPass(user.getAccount(),user.getPassword());
if(list != null && list.size() > 0){//说明登录成功
//2.1、登录成功
User user = list.get(0);
//2.1.1、根据用户id查询该用户的所有角色
user.setUserRoles(userService.getUserRolesByUserId(user.getId()));
//2.1.2、将用户信息保存到session中
ServletActionContext.getRequest().getSession().setAttribute(Constant.USER,user);
//2.1.3、将用户登录记录到日志文件
Log log = LogFactory.getLog(getClass());
log.info("用户名称为:" + user.getName() + " 的用户登录了系统。");
//2.1.4、重定向跳转到首页
return "home";
} else {//登录失败
loginResult = "帐号或密码不正确!";
}
} else {
loginResult = "帐号或密码不能为空!";
}
} else {
loginResult = "请输入帐号和密码!";
}
return toLoginUI();
}
//退出,注销
public String logout(){
//清除session中保存的用户信息
ServletActionContext.getRequest().getSession().removeAttribute(Constant.USER);
return toLoginUI();
}

配置login-struts.xml文件并引入struts.xml中。

7.3.1.2 项目首页重定向到登录页
改写WebRoot下面的index.jsp,在里面直接重定向到登录页。
《%@ page language="java" import="java.util.*"pageEncoding="utf-8"%》
《%
String path = request.getContextPath();
response.sendRedirect(path+"/sys/login_toLoginUI.action");
%》
7.4权限验证说明
在系统中,① 需要验证用户的登录,只有登录后才能访问系统的资源。②纳税服务子系统只有角色拥有“纳税服务”权限的才可以操作。
对于上述2种的权限验证,在此采用过滤器进行处理。编写LoginFilter过滤器,在过滤器中对用户访问的url进行登录验证,在登录的前提下再次验证如果访问的是纳税服务命名空间下的资源则利用权限验证接口PermissionCheck校验用户是否有“纳税服务”。

7.4.1登录过滤器
编写过滤器cn.itcast.core.filter.LoginFilter类;实现javax.servlet.Filter接口:
public class LoginFilter implements Filter{

@Override
public void destroy() {
}

@Override
public void doFilter(ServletRequest servletRequest,ServletResponse servletResponse,
FilterChain chain) throws IOException, ServletException{
HttpServletRequest request =(HttpServletRequest)servletRequest;
HttpServletResponse response =(HttpServletResponse)servletResponse;
String uri = request.getRequestURI();
//判断当前请求地址是否是登录的请求地址
if(!uri.contains("sys/login_")){
//非登录请求
if(request.getSession().getAttribute(Constant.USER) !=null){
//说明已经登录过
//判断是否访问纳税服务系统
if(uri.contains("/nsfw/")){
//访问纳税服务子系统
User user =(User)request.getSession().getAttribute(Constant.USER);
//获取spring容器
WebApplicationContext applicationContext =WebApplicationContextUtils.getWebApplicationContext(request.getSession().getServletContext());
PermissionCheck pc =(PermissionCheck)applicationContext.getBean("permissionCheck");
if(pc.isAccessible(user, "nsfw")){
//说明有权限,放行
chain.doFilter(request, response);
} else {
//没有权限,跳转到没有权限提示页面
response.sendRedirect(request.getContextPath() +"/sys/login_toNoPermissionUI.action");
}
} else {
//非访问纳税服务子系统,则直接放行
chain.doFilter(request, response);
}
} else {
//没有登录,跳转到登录页面
response.sendRedirect(request.getContextPath() +"/sys/login_toLoginUI.action");
}
} else {
//登录请求;直接放行
chain.doFilter(request, response);
}
}

@Override
public void init(FilterConfig arg0) throws ServletException{
}

}



在web.xml中配置该过滤器:
    《filter》
《filter-name》loginFilter《/filter-name》
《filter-class》cn.itcast.core.filter.LoginFilter《/filter-class》
《/filter》
《filter-mapping》
《filter-name》loginFilter《/filter-name》
《url-pattern》*.action《/url-pattern》
《/filter-mapping》
7.4.2鉴定权限
在过滤器中加入权限的鉴定;当用户登录的情况下如果访问特定模块需要验证用户是否有特定权限。由于权限常用于在用户使用系统时权限的鉴定,所以可以在用户实体中加入一个用户权限的集合来保存用户的角色集合。新增用户类中角色列表属性userRoles用于存放用户的角色列表。

PermissionCheck/PermissionCheckImpl
public interface PermissionCheck {

public boolean isAccessible(User user, String code);

}

public class PermissionCheckImpl implements PermissionCheck{
@Resource
private UserService userService;

@Override
public boolean isAccessible(User user, String code) {
//1、获取用户的所有角色
List《UserRole》 list = user.getUserRoles();
if(list == null){
list = userService.getUserRolesByUserId(user.getId());
}
//2、根据每个角色对于的所有权限进行对比
if(list != null && list.size()>0){
for(UserRole ur: list){
Role role = ur.getId().getRole();
for(RolePrivilege rp: role.getRolePrivileges()){
//对比是否有code对应的权限
if(code.equals(rp.getId().getCode())){
//说明有权限,返回true
return true;
}
}
}
}
return false;
}
}


在applicationContext.xml中需要注册PermissionCheckBean,主要是为了方便在使用鉴定权限时可以注入其它Service。
7.5解决细节-登录页面嵌套
在纳税服务的首页中使用了frameset,当前用户的系统登录信息失效后;如果再点击左边的菜单,那么在右边的显示登录页面,而正确的应该是整个页面返回到登录页。

解决这个问题:应该在跳转到登录页面中使用js脚本判断,是否当前页面在框架内,即当前页面的窗口是否是顶级窗口,如果是子窗口的话;可以直接刷新父窗口的地址则会自动地整个页面跳转为登录页。
《script type="text/javascript"》
if(window != window.parent){
window.parent.location.reload(true);
}
《/script》
0 0
原创粉丝点击