仰望星空——冲刺日志Day3

Part1 各个成员今日完成的任务

  • 20211302:开始客户端和服务器的开发,实现基本的公文传输功能。
  • 20211304:创建用户管理相关的数据库表,包括用户信息表。
  • 20211308:继续开发用户管理功能,包括用户信息的CRUD操作。
  • 20211317:继续完善访问控制功能,限制用户对公文的访问。
  • 20211318:继续测试国密算法的集成,确保加密和解密功能正常。

访问控制检验

package cn.edu.nuc.article.controller;

import java.io.IOException;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import cn.edu.nuc.article.util.SM4Utils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import cn.edu.nuc.article.entity.Function;
import cn.edu.nuc.article.entity.Role;
import cn.edu.nuc.article.entity.User;
import cn.edu.nuc.article.service.ArticleService;
import cn.edu.nuc.article.service.RoleService;
import cn.edu.nuc.article.service.UserService;
import cn.edu.nuc.article.util.CodeUtil;
import cn.edu.nuc.article.util.MD5Helper;

/**
 * 用户登录和加载首页Controller
 * @author 仰望星空
 *
 */
@Controller
public class LoginController {
	
	/**
	 * 用户业务
	 */
	@Autowired
	private UserService userService;
	
	/**
	 * 角色业务
	 */
	@Autowired
	private RoleService roleService;
	
	/**
	 * 公文Service
	 */
	@Autowired
	private ArticleService articleService;
	
	/**
	 * 获取验证码
	 * @param request
	 * @param response
	 * @throws ServletException
	 * @throws IOException
	 */
	@RequestMapping(value = "/captcha", method = RequestMethod.GET)
    @ResponseBody
    public void captcha(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
		
		CodeUtil.drawCode(request, response);
    }
	
	/**
	 * 用户注销
	 * @param session
	 * @return
	 */
	@RequestMapping("/logout")
	public String logout(HttpSession session) {
		
		//移除user属性
		session.removeAttribute("user");
		
		//注销Session
		session.invalidate();
		
		//返回登录界面
		return "redirect:/login.jsp";
	}

	/**
	 * 用户登录操作
	 * @param map 保存结果集
	 * @param session 存取用户信息
	 * @param loginname 提交的登录名
	 * @param password 提交的密码
	 * @param code 提交的验证码
	 * @return
	 */
	@RequestMapping("/login")
	public String userLogin(Map<String, Object> map, HttpSession session, 
			String loginname, String password, String code) {
		
		//1.首先检查登录名、密码和验证码用户是否都填写了,如果有一样没填写就直接打回去
		
		if (!StringUtils.hasText(loginname) || !StringUtils.hasText(password)
				|| !StringUtils.hasText(code)) {
			
			//1.1 告诉用户登陆失败,这三个字段都是必填项
			map.put("msg", "登录名、密码和验证码都是必填项!");
			map.put("result", false);
			
			//1.2 直接跳回登录界面
			return "forward:/login.jsp";
		} 
		
		//2.检查验证码填写是否正确,如不正确,也要打回去
		String randomString = (String) session.getAttribute("code");
		if (!randomString.equalsIgnoreCase(code)) {
			
			//2.1 告诉用户验证码输入错误
			map.put("msg", "验证码输入错误!");
			map.put("result", false);
			
			//2.2 直接跳回登录界面
			return "forward:/login.jsp";
		}
		
		//3.检查用户输入的账号是否正确
		
		//3.1 去数据库查询用户名和密码的组合
		
		//对用户输入的密码明文进行加密,获得密文
//		MD5Helper md5Helper = new MD5Helper();
//		String afterEncode = md5Helper.getTwiceMD5ofString(password);

		String key = "975C7238C3824FB0";
		System.out.println("ECB模式加密");
		String afterEncode = SM4Utils.encryptSm4(password,key);
		
		//检查用户名密码(直接用密文查询)
		User user = userService.loginValidate(loginname, afterEncode);
		
		//3.2 检查登录验证是否通过,根据结果跳转
		if(user != null) { 
			//3.2.1 验证通过
			
			//3.2.1.1 如果验证通过,就要把用户信息存入Session,供以后登陆拦截检查
			session.setAttribute("user", user);
			
			//3.2.1.2 跳转到首页
			return "forward:/toIndex";
		} else {
			//3.2.2 验证不通过
			
			//3.2.2.1 提示用户登陆失败原因:用户名密码组合不正确
			map.put("msg", "登录名密码组合输入有误或登录名不存在!");
			map.put("result", false);
			
			return "forward:/login.jsp";
		}
		
	}
	
	/**
	 * 访问首页
	 * @return
	 */
	@RequestMapping("/toIndex")
	public String toIndex(Map<String, Object> map, HttpSession session) {
		
		//1.从Session中加载出用户的信息
		User user = (User) session.getAttribute("user");
		
		//2.通过用户信息找到用户的角色信息
		Role role = user.getRole();
		
		//3.通过角色信息查出角色下面的功能
		List<Function> functions = roleService.findByIdCascade(role.getRoleid()).getFunctionList();
		map.put("functionList", functions);
		
		return "index";
	}
	
	/**
	 * 访问欢迎页
	 * @param map
	 * @return
	 */
	@RequestMapping("/toWelcome")
	public String toWelcome(Map<String, Object> map, HttpSession session) {
		
		//1.从Session中取出用户信息,并得到用户id和角色id
		User user = (User) session.getAttribute("user");
		Integer userId = user.getUserid();
		Integer roleid = user.getRoleId();
		
		//2.找出要统计的4个数字
		
		//2.1 找出待处理公文数量
		Long dealcount = null;
		if (roleid == 1 || roleid == 2) {
			dealcount = articleService.getDealCount(userId);
		}
		
		//2.2 找出审核驳回公文数量
		Long failcount = articleService.getFailCount(userId);
		
		//2.3 找出待接收公文数量
		Long receivecount = articleService.getReceivedCount(userId);
		
		//2.4 找出等待审核通过公文数量
		Long waitcount = articleService.getWaitCount(userId);
		
		//3 保存查询结果
		map.put("dealcount", dealcount);
		map.put("failcount", failcount);
		map.put("receivecount", receivecount);
		map.put("waitcount", waitcount);
		
		//4.返回首页
		return "home";
	}

}

设计数据结构中联系人树

package cn.edu.nuc.article.dto;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;

/**
 * 联系人树的数据传输对象
 * @author Administrator
 *
 */
@JsonInclude(Include.NON_NULL)
public class TreeDto implements Serializable {
	
	/**
	 * 序列化id
	 */
	private static final long serialVersionUID = -738769624230897381L;

	/**
	 * 节点显示的文字
	 */
	private String text;
	
	/**
	 * 子节点
	 */
	private List<TreeDto> nodes;
	
	/**
	 * 节点的id,也就是用户id
	 */
	private Integer id;
	
	/**
	 * 控制节点是否被选中
	 */
	private State state;

	public String getText() {
		return text;
	}

	public void setText(String text) {
		this.text = text;
	}

	public List<TreeDto> getNodes() {
		return nodes;
	}

	public void setNodes(List<TreeDto> nodes) {
		this.nodes = nodes;
	}
	
	public void addNode(TreeDto treeDto) {
		if (nodes == null) {
			nodes = new ArrayList<>();
		}
		nodes.add(treeDto);
	}

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public State getState() {
		return state;
	}

	public void setState(State state) {
		this.state = state;
	}

	@Override
	public String toString() {
		return "TreeDto [text=" + text + ", nodes=" + nodes + ", id=" + id + ", state=" + state + "]";
	}
}

角色访问控制权限设计

package cn.edu.nuc.article.controller;

import java.util.List;
import java.util.Map;

import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;

import cn.edu.nuc.article.entity.Function;
import cn.edu.nuc.article.entity.Role;
import cn.edu.nuc.article.service.FunctionService;
import cn.edu.nuc.article.service.RoleService;

/**
 * 角色Controller
 * @author 仰望星空
 *
 */
@Controller
@RequestMapping("/role")
public class RoleController {

	/**
	 * 角色Service
	 */
	@Autowired
	private RoleService roleService;
	
	/**
	 * 功能Service
	 */
	@Autowired
	private FunctionService functionService;
	
	/**
	 * 更新权限
	 * @param map
	 * @param roleid 角色id
	 * @param funids 用户选中的权限id
	 * @return
	 */
	@RequestMapping("/updateRoleRight")
	public String updateRoleRight(Map<String, Object> map, Integer roleid, Integer funids[]) {
		
		//查出角色信息
		Role role = roleService.findById(roleid);
		
		//修改权限列表
		boolean result = roleService.updateRoleright(roleid, funids);
		map.put("result", result);
		
		if (result == true) {
			map.put("msg", "修改角色[" + role.getRolename() + "]的权限信息成功!");
		} else {
			map.put("msg", "修改角色[" + role.getRolename() + "]的权限信息失败!");
		}
		
		return "forward:/role/roles";
	}
	
	/**
	 * 进入权限页面
	 * @return
	 */
	@RequestMapping("/toRoleRight")
	public String toRoleRight(Map<String, Object> map, Integer roleid) {
		
		//得到权限列表
		Role role = roleService.findByIdCascade(roleid);
		map.put("role", role);
		
		//得到所有功能信息
		List<Function> functions = functionService.getFunctionList(null);
		map.put("functionList", functions);
		
		return "role/roleright";
	}
	
	/**
	 * 进入修改页面
	 * @return
	 */
	@RequestMapping("/toModify")
	public String toModify(Map<String, Object> map, Integer roleid) {
		
		Role role = roleService.findById(roleid);
		map.put("role", role);
		
		return "role/rolemodify";
	}
	
	/**
	 * 修改角色
	 * @return
	 */
	@RequestMapping("/modifyRole")
	public String modifyRole(Map<String, Object> map, @Valid Role role, BindingResult bindingResult) {
		
		//检查校验是否出错
		if(bindingResult.hasErrors()){
			List<ObjectError> list = bindingResult.getAllErrors();
			ObjectError oe = list.get(0);
			
			//校验失败信息
			map.put("result", false);
			map.put("msg", oe.getDefaultMessage() + "修改角色[" + role.getRolename() + "]失败!");
		} else {
			//功能名称查重
			boolean hasSame = roleService.hasSameRole(role.getRoleid(), role.getRolename());
			
			if (hasSame == false) { //功能名称不重复
				
				//保存功能信息,拿到修改操作的结果
				boolean result = roleService.updateRole(role);
				map.put("result", result);
				
				//根据操作结果生成提示信息
				if (result == true) {  //修改成功且无重复
					
					map.put("msg", "修改角色[" + role.getRolename() + "]成功!");
				} else {
					
					map.put("msg", "修改角色[" + role.getRolename() + "]失败!");
				}
				
			} else {
				map.put("result", false);
				map.put("msg", "角色名称[" + role.getRolename() + "]重复,修改角色失败!");
			}
		}
			
		return "forward:/role/roles";
		
	}
	
	/**
	 * 进入添加页面
	 * @return
	 */
	@RequestMapping("/toAdd")
	public String toAdd() {
		
		return "role/roleadd";
	}
	
	/**
	 * 添加角色
	 * @return
	 */
	@RequestMapping("/addRole")
	public String addRole(Map<String, Object> map, @Valid Role role, BindingResult bindingResult) {
		
		//检查校验是否出错
		if(bindingResult.hasErrors()){
			List<ObjectError> list = bindingResult.getAllErrors();
			ObjectError oe = list.get(0);
			
			//校验失败信息
			map.put("result", false);
			map.put("msg", oe.getDefaultMessage() + "添加角色[" + role.getRolename() + "]失败!");
		} else {
			//功能名称查重
			boolean hasSame = roleService.hasSameRole(null, role.getRolename());
			
			if (hasSame == false) { //功能名称不重复
				
				//保存功能信息,拿到添加操作的结果
				boolean result = roleService.addRole(role);
				map.put("result", result);
				
				//根据操作结果生成提示信息
				if (result == true) {  //添加成功且无重复
					
					map.put("msg", "添加角色[" + role.getRolename() + "]成功!");
				} else {
					
					map.put("msg", "添加角色[" + role.getRolename() + "]失败!");
				}
				
			} else {
				map.put("result", false);
				map.put("msg", "角色名称[" + role.getRolename() + "]重复,添加角色失败!");
			}
		}
			
		return "forward:/role/roles";
		
	}
	
	/**
	 * 模糊查询
	 * @param map 容器
	 * @param pageNo 目标页
	 * @param pageCount 每页记录数
	 * @param roleid 角色id
	 * @return
	 */
	@RequestMapping("/roles")
	public String roles(Map<String, Object> map,
			@RequestParam(value="pageNo", defaultValue="1", required=false) Integer pageNo,
			@RequestParam(value="pageCount", defaultValue="10", required=false) Integer pageCount,
			@RequestParam(value="role_id", required=false) Integer role_id) {
		
		// 引入PageHelper分页插件
		// 在查询之前只需要调用,传入页码,以及每页的大小
		PageHelper.startPage(pageNo, pageCount);
		
		// 分页查询得到结果集
		List<Role> roles;
		
		if (role_id != null) {
			Role role = new Role();
			role.setRoleid(role_id);
			roles = roleService.getByKeyword(role);
		} else {
			roles = roleService.getByKeyword(null);
		}
		
		
		// 使用pageInfo包装查询后的结果,只需要将pageInfo交给页面就行了。
		// 封装了详细的分页信息,包括有我们查询出来的数据,传入连续显示的页数
		PageInfo<Role> page = new PageInfo<Role>(roles, 5);
		
		//保存结果集带到页面显示
		map.put("page", page);
		map.put("pageNo", pageNo);
		map.put("pageCount", pageCount);
		map.put("allList", roleService.getByKeyword(null));
		
		//保存模糊查询条件以便回显
		map.put("role_id", role_id);
		
		return "role/roleManage";
	}
	
}

Part2 各个成员遇到的问题

  • 开始客户端和服务器的开发(20211302):技术选型问题: 选择适合客户端和服务器开发的技术栈可能涉及到前端框架、后端框架、通信协议等。进行技术调研,选择符合项目需求的技术栈。可以考虑团队成员的熟悉度、社区活跃度、文档完整性等因素。可以进行原型开发和小规模试验,评估不同技术的适用性。
  • 创建用户管理相关的数据库表(20211304):数据库设计问题: 设计用户信息表时,可能面临表结构的规划和关联关系的确定。进行数据库规模估算,设计灵活的表结构,确保符合数据库范式要求。可以借助数据库设计工具,考虑将用户信息表与其他相关表建立关联关系。
  • 继续开发用户管理功能(20211308):安全性问题: 在用户信息的 CRUD 操作中,可能涉及到安全性问题,如数据的保护、身份验证等。使用参数化查询、ORM(对象关系映射)等方式,防止 SQL 注入攻击。采用安全的身份验证和授权机制,确保只有授权用户能够进行敏感操作。
  • 继续完善访问控制功能(20211317):精细化访问控制难度: 在访问控制功能中,可能需要对用户权限进行更细粒度的控制,这可能增加开发难度。使用 RBAC(基于角色的访问控制)或 ABAC(基于属性的访问控制)等访问控制模型,以更灵活地管理用户权限。通过仔细的需求分析,定义清晰的权限策略。
  • 继续测试国密算法的集成(20211318):性能问题和算法正确性: 集成国密算法后,可能面临性能问题和需要确保加密和解密功能的正确性。进行国密算法的性能测试和功能测试,确保在实际使用场景下能够满足性能要求。使用测试向量验证加密和解密的正确性。可以使用性能分析工具,优化算法或硬件加速以提高性能。

Part3 明日各个成员的任务安排

  • 20211302:继续开发公文传输功能,实现文件的上传和下载。
  • 20211304:设计权限表,为访问控制做准备。
  • 20211308:完成用户管理功能,包括权限分配。
  • 20211317:继续完善访问控制功能,实现权限检查。
  • 20211318:进行国密算法的性能优化和测试。

Part4 各个成员今日对项目的贡献量

image

Part5 燃尽图与站立式会议照片

image

posted @ 2023-11-24 11:16  DKY——仰望星空  阅读(8)  评论(0编辑  收藏  举报
$