SSM 项目:企业权限管理系统(三)

此博客用于个人学习,来源于ssm框架的书籍,对知识点进行一个整理。

第三章 SSM 权限操作:

1. 数据库与表结构:


1.1 用户表:

用户表信息描述 users:

序号字段名称字段类型字段描述
1idvarchar2无意义,主键uuid
2emailvarchar2非空,唯一
3usernamevarchar2用户名
4passwordvarchar2密码(加密)
5phoneNumvarchar2电话
6statusint状态0 未开启 1 开启

sql 语句:

CREATE TABLE users( 
	id varchar2(32) default SYS_GUID() PRIMARY KEY, 
	email VARCHAR2(50) UNIQUE NOT NULL, 
	username VARCHAR2(50), 
	PASSWORD VARCHAR2(50), 
	phoneNum VARCHAR2(20), 
	STATUS INT 
)

实体类 UserInfo:

public class UserInfo { 
	private String id; 
	private String username; 
	private String email; 
	private String password; 
	private String phoneNum; 
	private int status; 
	private String statusStr; 
	private List<Role> roles;
	//其他get/set方法
}

1.2 角色表:

角色表信息描述 role:

序号字段名称字段类型字段描述
1idvarchar2无意义,主键uuid
2roleNamevarchar2角色名
3roleDescvarchar2角色描述

sql 语句:

CREATE TABLE role( 
	id varchar2(32) default SYS_GUID() PRIMARY KEY, 
	roleName VARCHAR2(50) , 
	roleDesc VARCHAR2(50) 
)

实体类 Role:

public class Role { 
	private String id; 
	private String roleName; 
	private String roleDesc; 
	private List<Permission> permissions; 
	private List<User> users; 
	//其他get/set方法
}

1.3 中间表 users_role:

用户与角色之间是多对多关系,我们通过 user_role 表来描述其关联,在实体类中User中存在 List,在 Role 中有 List:

CREATE TABLE users_role( 
	userId varchar2(32), 
	roleId varchar2(32), 
	PRIMARY KEY(userId,roleId), 
	FOREIGN KEY (userId) REFERENCES users(id), 
	FOREIGN KEY (roleId) REFERENCES role(id) 
)

1.4 资源权限表:

权限资源表描述 permission:

序号字段名称字段类型字段描述
1idvarchar2无意义,主键uuid
2permissionNamevarchar2权限名
3urlvarchar2资源路径

sql 语句:

CREATE TABLE permission( 
	id varchar2(32) default SYS_GUID() PRIMARY KEY, 
	permissionName VARCHAR2(50) , 
	url VARCHAR2(50) 
)

实体类 :

public class Permission { 
	private String id; 
	private String permissionName; 
	private String url; 
	private List<Role> roles; 
	//其他get/set方法
}

1.5 中间表 role_permission:

权限资源与角色是多对多关系,我们使用 role_permission 表来描述。在实体类 Permission 中存在 List ,在 Role 类中有 List。

CREATE TABLE role_permission( 
	permissionId varchar2(32), 
	roleId varchar2(32), 
	PRIMARY KEY(permissionId,roleId), 
	FOREIGN KEY (permissionId) REFERENCES permission(id), 
	FOREIGN KEY (roleId) REFERENCES role(id) 
)

2. 用户管理:


2.1 用户登录:

在 web 层的资源包下创建 spring-security.xml 文件,配置 spring security 。

<!-- 切换成数据库中的用户名和密码 -->
<security:authentication-manager>
    <security:authentication-provider user-service-ref="userService">
        <!-- 配置加密的方式
        <security:password-encoder ref="passwordEncoder"/>-->
    </security:authentication-provider>
</security:authentication-manager>

创建登录页面 login.jsp。

Service:先定义接口 IUserService,继承 UserDetailsService,然后定义它的实现类 IUserServiceImpl,注入 IUserDao,实现方法 loadUserByUsername。

public interface IUserService extends UserDetailsService {
}

@Service("userService")
@Transactional
public class UserServiceImpl implements IUserService {

    @Autowired
    private IUserDao userDao;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        UserInfo userInfo = null;
        try {
            userInfo = userDao.findByUsername(username);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //处理自己的用户对象封装成UserDetails
        //  User user=new User(userInfo.getUsername(),"{noop}"+userInfo.getPassword(),getAuthority(userInfo.getRoles()));
        User user = new User(userInfo.getUsername(), "{noop}" + userInfo.getPassword(), userInfo.getStatus() == 0 ? false : true, true, true, true, getAuthority(userInfo.getRoles()));
        return user;
    }

	//作用就是返回一个List集合,集合中装入的是角色描述
    public List<SimpleGrantedAuthority> getAuthority(List<Role> roles) {

        List<SimpleGrantedAuthority> list = new ArrayList<>();
        for (Role role : roles) {
            list.add(new SimpleGrantedAuthority("ROLE_" + role.getRoleName()));
        }
        return list;
    }
}

Dao:定义接口 IUserDao 接口,添加方法 findByUsername:

public interface IUserDao {

    @Select("select * from users where username=#{username}")
    @Results({
            @Result(id = true, property = "id", column = "id"),
            @Result(property = "username", column = "username"),
            @Result(property = "email", column = "email"),
            @Result(property = "password", column = "password"),
            @Result(property = "phoneNum", column = "phoneNum"),
            @Result(property = "status", column = "status"),
            @Result(property = "roles",column = "id",javaType = java.util.List.class,many = @Many(select = "com.itheima.ssm.dao.IRoleDao.findRoleByUserId"))
    })
    public UserInfo findByUsername(String username) throws Exception;
}

2.2 用户退出:

在 spring-security.xml 文件中进行配置:

 <!-- 退出 -->
<security:logout invalidate-session="true" logout-url="/logout.do" logout-success-url="/login.jsp" />

在 login.jsp 中添加注销的链接:

<a href="${pageContext.request.contextPath}/logout.do" class="btn btn-default btn-flat">注销</a>

2.3 用户查询:

创建用户查询页面 user-list.jsp。

定义 UserController 类,添加 findAll 方法,然后在 service 和 dao 中添加方法。

@Controller
@RequestMapping("/user")
public class UserController {

    @Autowired
    private IUserService userService;

    @RequestMapping("/findAll.do")
    public ModelAndView findAll() throws Exception {
        ModelAndView mv = new ModelAndView();
        List<UserInfo> userList = userService.findAll();
        mv.addObject("userList", userList);
        mv.setViewName("user-list");
        return mv;
    }
}

public interface IUserService extends UserDetailsService {
    List<UserInfo> findAll() throws Exception;
}

public interface IUserDao {

    @Select("select * from users")
    List<UserInfo> findAll() throws Exception;
}

2.4 用户添加:

创建用户添加页面 user-add.jsp。

Controller:在 UserController 类添加 save 方法,注入 service。

@Controller
@RequestMapping("/user")
public class UserController {

    @Autowired
    private IUserService userService;

    //用户添加
    @RequestMapping("/save.do")
    public String save(UserInfo userInfo) throws Exception {
        userService.save(userInfo);
        return "redirect:findAll.do";
    }

    @RequestMapping("/findAll.do")
    public ModelAndView findAll() throws Exception {
        ModelAndView mv = new ModelAndView();
        List<UserInfo> userList = userService.findAll();
        mv.addObject("userList", userList);
        mv.setViewName("user-list");
        return mv;
    }
}

Service:定义 UserService 接口及其实现类,注入 UserDao,注入 BCryptPasswordEncoder 类用于加密。

@Service("userService")
@Transactional
public class UserServiceImpl implements IUserService {

    @Autowired
    private IUserDao userDao;
    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Override
    public UserInfo findById(String id) throws Exception{

        return  userDao.findById(id);
    }

    @Override
    public void save(UserInfo userInfo) throws Exception {
        //对密码进行加密处理
        userInfo.setPassword(bCryptPasswordEncoder.encode(userInfo.getPassword()));
        userDao.save(userInfo);
    }
}

在 spring-security.xml 类中配置加密类。

<!-- 配置加密类 -->
<bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>

Dao:在 IUserDao 接口中添加 save 方法。

public interface IUserDao {

    @Insert("insert into users(email,username,password,phoneNum,status) values(#{email},#{username},#{password},#{phoneNum},#{status})")
    void save(UserInfo userInfo) throws Exception;
}

2.5 用户详情:

创建用户详情页面 user-show.jsp。

Controller:定义 UserController 类,注入 UserService,添加 findById 方法。

@Controller
@RequestMapping("/user")
public class UserController {

    @Autowired
    private IUserService userService;

    //查询指定id的用户
    @RequestMapping("/findById.do")
    public ModelAndView findById(String id) throws Exception{
        ModelAndView mv = new ModelAndView();
        UserInfo userInfo = userService.findById(id);
        mv.addObject("user",userInfo);
        mv.setViewName("user-show1");
        return mv;
    }
}

Dao:在 IUserDao 接口中添加 findById 方法,关联查询出 role 的信息。

public interface IUserDao {

    @Select("select * from users where id=#{id}")
    @Results({
            @Result(id = true, property = "id", column = "id"),
            @Result(property = "username", column = "username"),
            @Result(property = "email", column = "email"),
            @Result(property = "password", column = "password"),
            @Result(property = "phoneNum", column = "phoneNum"),
            @Result(property = "status", column = "status"),
            @Result(property = "roles",column = "id",javaType = java.util.List.class,many = @Many(select = "com.itheima.ssm.dao.IRoleDao.findRoleByUserId"))
    })
    UserInfo findById(String id) throws Exception;
}

由于此时用户表与角色表是多对多的关系,于是在 IRoleDao 接口中也需要添加 findRoleByUserId 方法,关联查询出 permission 的信息。

public interface IRoleDao {

    //根据用户id查询出所有对应的角色
    @Select("select * from role where id in (select roleId from users_role where userId=#{userId})")
    @Results({
            @Result(id = true, property = "id", column = "id"),
            @Result(property = "roleName", column = "roleName"),
            @Result(property = "roleDesc", column = "roleDesc"),
            @Result(property = "permissions",column = "id",javaType = java.util.List.class,many = @Many(select = "com.itheima.ssm.dao.IPermissionDao.findPermissionByRoleId"))
    })
    public List<Role> findRoleByUserId(String userId) throws Exception;
}

由于此时角色表与资源权限表是多对多的关系,于是在 IPermissionDao 接口中也需要添加 findByRoleId 方法。

public interface IPermissionDao {

    @Select("select * from permission where id in (select permissionId from role_permission where roleId=#{id} )")
    public List<Permission> findPermissionByRoleId(String id) throws Exception;
}

3. 角色管理:


3.1 角色查询:

创建角色信息展示页面 role-list.jsp。

Controller:定义 RoleController 类,注入 roleService 类,添加 findAll 方法。

@RequestMapping("/role")
@Controller
public class RoleController {

    @Autowired
    private IRoleService roleService;

    @RequestMapping("/findAll.do")
    public ModelAndView findAll() throws Exception {
        ModelAndView mv = new ModelAndView();
        List<Role> roleList = roleService.findAll();
        mv.addObject("roleList", roleList);
        mv.setViewName("role-list");
        return mv;
    }
}

Dao:在 IRoleDao 中添加 findAll 方法。

public interface IUserDao {

    @Select("select * from users")
    List<UserInfo> findAll() throws Exception;
}

3.2 角色添加:

创建角色添加页面 role-add.jsp。

Controller:在 RoleController 类中添加 save 方法。

@RequestMapping("/role")
@Controller
public class RoleController {

    @Autowired
    private IRoleService roleService;

    @RequestMapping("/save.do")
    public String save(Role role) throws Exception {
        roleService.save(role);
        return "redirect:findAll.do";
    }
}

Dao:在 IRoleDao 中添加 save 方法。

public interface IRoleDao {

    @Insert("insert into role(roleName,roleDesc) values(#{roleName},#{roleDesc})")
    void save(Role role);
}

4. 资源权限管理:


4.1 资源权限查询:

创建权限资源页面 permission-list.jsp。

Controller:定义 PermissionController 类,注入 permissionService 类,添加 findAll 方法。

@Controller
@RequestMapping("/permission")
public class PermissionController {

    @Autowired
    private IPermissionService permissionService;

    @RequestMapping("/findAll.do")
    public ModelAndView findAll() throws Exception {
        ModelAndView mv=new ModelAndView();
        List<Permission> permissionList = permissionService.findAll();
        mv.addObject("permissionList",permissionList);
        mv.setViewName("permission-list");
        return mv;
    }
}

Dao:在 IPermissionDao 中添加 findAll 方法。

public interface IPermissionDao {

    @Select("select * from permission")
    List<Permission> findAll() throws Exception;
}

4.2 资源权限添加:

创建权限资源添加页面 permission-add.jsp。

Controller:在 PermissionController 类中添加 save 方法。

@Controller
@RequestMapping("/permission")
public class PermissionController {

    @Autowired
    private IPermissionService permissionService;

    @RequestMapping("/save.do")
    public String save(Permission permission) throws Exception {
        permissionService.save(permission);
        return "redirect:findAll.do";
    }
}

Dao:在 IPermissionDao 中添加 save 方法。

public interface IPermissionDao {

    @Insert("insert into permission(permissionName,url) values(#{permissionName},#{url})")
    void save(Permission permission) throws Exception;
}

5. 权限关联与控制:


5.1 用户角色关联:

用户与角色之间是多对多关系,我们要建立它们之间的关系,只需要在中间表user_role插入数据即可。

在 user-list.jsp 页面上添加链接用于添加角色。

<a href="${pageContext.request.contextPath}/user/findUserByIdAndAllRole.do?id=${user.id}" class="btn bg-olive btn-xs">添加角色</a>

创建用于添加角色的页面 user-roe-add.jsp。

Controller:在 UserController 中,添加 findUserByIdAndAllRole 方法,用于查询用户以及用户可以添加的角色;添加 addRoleToUser 方法,用于用户添加角色。

@Controller
@RequestMapping("/user")
public class UserController {

    @Autowired
    private IUserService userService;

	//给用户添加角色
    @RequestMapping("/addRoleToUser.do")
    public String addRoleToUser(@RequestParam(name = "userId", required = true) String userId, @RequestParam(name = "ids", required = true) String[] roleIds) {
        userService.addRoleToUser(userId, roleIds);
        return "redirect:findAll.do";
    }

    //查询用户以及用户可以添加的角色
    @RequestMapping("/findUserByIdAndAllRole.do")
    public ModelAndView findUserByIdAndAllRole(@RequestParam(name = "id", required = true) String userid) throws Exception {
        ModelAndView mv = new ModelAndView();
        //1.根据用户id查询用户
        UserInfo userInfo = userService.findById(userid);
        //2.根据用户id查询可以添加的角色
        List<Role> otherRoles = userService.findOtherRoles(userid);
        mv.addObject("user", userInfo);
        mv.addObject("roleList", otherRoles);
        mv.setViewName("user-role-add");
        return mv;
    }
}

Service:在 IUserService 以及实现类中添加 addRoleToUser 和 findOtherRoles 方法。

@Service("userService")
@Transactional
public class UserServiceImpl implements IUserService {

    @Autowired
    private IUserDao userDao;

    @Override
    public void addRoleToUser(String userId, String[] roleIds) {

        for(String roleId:roleIds){
            userDao.addRoleToUser(userId,roleId);
        }
    }
	
	@Override
    public List<Role> findOtherRoles(String userId) {
        return userDao.findOtherRoles(userId);
    }
}

Dao:在 IUserDao 接口中添加 findOtherRoles 和 addRoleToUser 方法。

public interface IUserDao {

	//用于查找可以添加的角色
    @Select("select * from role where id not in (select roleId from users_role where userId=#{userId})")
    List<Role> findOtherRoles(String userId);

	//用于添加用户与角色关系
    @Insert("insert into users_role(userId,roleId) values(#{userId},#{roleId})")
    void addRoleToUser(@Param("userId") String userId, @Param("roleId") String roleId);
}

5.2 角色权限关联:

角色与权限之间是多对多关系,我们要建立它们之间的关系,只需要在中间表role_permission插入数据即可。

在 role-list.jsp 页面上添加链接用于添加权限。

<a href="${pageContext.request.contextPath}/role/findRoleByIdAndAllPermission.do? id=${role.id}" class="btn bg-olive btn-xs">添加权限</a>

创建用于添加权限的页面 role-permission-add.jsp。

Controller:在 RoleController 中,添加 findRoleByIdAndAllPermission 方法,用于查询角色以及角色可以添加的权限;添加 addPermissionToRole 方法,用于角色添加权限。

@RequestMapping("/role")
@Controller
public class RoleController {

    @Autowired
    private IRoleService roleService;

    //给角色添加权限
    @RequestMapping("/addPermissionToRole.do")
    public String addPermissionToRole(@RequestParam(name = "roleId", required = true) String roleId, @RequestParam(name = "ids", required = true) String[] permissionIds) throws Exception {
        roleService.addPermissionToRole(roleId, permissionIds);
        return "redirect:findAll.do";
    }

    //根据roleId查询role,并查询出可以添加的权限
    @RequestMapping("/findRoleByIdAndAllPermission.do")
    public ModelAndView findRoleByIdAndAllPermission(@RequestParam(name = "id", required = true) String roleId) throws Exception {
        ModelAndView mv = new ModelAndView();
        //根据roleId查询role
        Role role = roleService.findById(roleId);
        //根据roleId查询可以添加的权限
        List<Permission> otherPermissions = roleService.findOtherPermissions(roleId);
        mv.addObject("role", role);
        mv.addObject("permissionList", otherPermissions);
        mv.setViewName("role-permission-add");
        return mv;
    }
}

Service:在 IUserService 以及实现类中添加 addPermissionToRole 和 findOtherPermissions 方法。

@Service
@Transactional
public class RoleServiceImpl implements IRoleService {

    @Autowired
    private IRoleDao roleDao;

    @Override
    public void addPermissionToRole(String roleId, String[] permissionIds) {
        for(String permissionId:permissionIds){
            roleDao.addPermissionToRole(roleId,permissionId);
        }
    }

    @Override
    public List<Permission> findOtherPermissions(String roleId) {
        return roleDao.findOtherPermissions(roleId);
    }
}

Dao:在 IRoleDao 接口中添加 findOtherPermissions 和 addPermissionToRole 方法。

public interface IRoleDao {
 
    @Select("select * from permission where id not in (select permissionId from role_permission where roleId=#{roleId})")
    List<Permission> findOtherPermissions(String roleId);

    @Insert("insert into role_permission(roleId,permissionId) values(#{roleId},#{permissionId})")
    void addPermissionToRole(@Param("roleId") String roleId, @Param("permissionId") String permissionId);
}

5.3 服务器端方法级权限控制:

有几种注解可以使用,这次使用支持表达式的注解 @PreAuthorize。

在 spring-security.xml 中将其开启。

<security:global-method-security pre-post-annotations="enabled" jsr250-annotations="enabled" secured-annotations="enabled"></security:global-method-security>

在 UserController 类中的 save 和 findAll 方法上添加此注解,用于对用户的某些权限操作做一个限制。

//用户添加
@RequestMapping("/save.do")
@PreAuthorize("authentication.principal.username == 'tom'")
public String save(UserInfo userInfo) throws Exception {
    userService.save(userInfo);
    return "redirect:findAll.do";
}

@RequestMapping("/findAll.do")
@PreAuthorize("hasRole('ROLE_ADMIN')")
public ModelAndView findAll() throws Exception {
    ModelAndView mv = new ModelAndView();
    List<UserInfo> userList = userService.findAll();
    mv.addObject("userList", userList);
    mv.setViewName("user-list");
    return mv;
}

在 aside.jsp 上对 “用户管理” 的标签上添加 <security:authorize access=“hasRole(‘ADMIN’)”> 包围,防止没有操作用户权限的用户页面上有此项功能。

<ul class="treeview-menu">
	<li id="system-setting">
		<security:authorize access="hasRole('ADMIN')">
		<a href="${pageContext.request.contextPath}/user/findAll.do"> 
			<i class="fa fa-circle-o"></i> 用户管理
		</a>
		</security:authorize>
	</li>
	<li id="system-setting">
		<a href="${pageContext.request.contextPath}/role/findAll.do"> 
		<i class="fa fa-circle-o"></i> 角色管理
	</a>
	</li>
	<li id="system-setting">
		<a href="${pageContext.request.contextPath}/permission/findAll.do">
		<i class="fa fa-circle-o"></i> 资源权限管理
	</a>
	</li>
	<li id="system-setting">
		<a href="${pageContext.request.contextPath}/sysLog/findAll.do"> 
		<i class="fa fa-circle-o"></i> 访问日志
	</a>
	</li>
</ul>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值