仰望星空——冲刺日志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 各个成员今日对项目的贡献量
Part5 燃尽图与站立式会议照片