详解spring整合shiro权限管理与数据库设计

网友投稿 282 2023-05-12


详解spring整合shiro权限管理与数据库设计

之前的文章中我们完成了基础框架的搭建,现在基本上所有的后台系统都逃不过权限管理这一块,这算是一个刚需了。现在我们来集成shiro来达到颗粒化权限管理,也就是从连接菜单到页面功能按钮,都进行权限都验证,从前端按钮的显示隐藏,到后台具体功能方法的权限验证。

首先要先设计好我们的数据库,先来看一张比较粗糙的数据库设计图:

具体的数据库设计代码

/*

Navicat mysql Data Transfer

Source Server : 本机

Source Server Version : 50537

Source Host : localhost:3306

Source Database : task

Target Server Type : MYSQL

Target Server Version : 50537

File Encoding : 65001

Date: 2017-01-19 09:58:27

*/

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------

-- Table structure for sys_authority

-- ----------------------------

DROP TABLE IF EXISTS `sys_authority`;

CREATE TABLE `sys_authority` (

`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',

`data_url` varchar(100) NOT NULL COMMENT '连接路径或方法',

`menu_class` varchar(50) NOT NULL COMMENT '菜单样式',

`menu_code` varchar(50) NOT NULL COMMENT '菜单编码',

`menu_name` varchar(50) NOT NULL COMMENT '菜单名称',

`parent_menucode` varchar(50) DEFAULT NULL COMMENT '上级菜单编码',

`sequence` bigint(20) DEFAULT '0' COMMENT '排序',

`menu_type` varchar(2) DEFAULT '1' COMMENT '菜单类型(1是左导航菜单 2是按钮权限)',

`create_time` varchar(30) NOT NULL COMMENT '创建时间',

PRIMARY KEY (`id`),

UNIQUE KEY `uk_sys_authority_menu_code` (`menu_code`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='菜单表';

-- ----------------------------

-- Records of sys_authority

-- ----------------------------

-- ----------------------------

-- Table structure for sys_department

-- ----------------------------

DROP TABLE IF EXISTS `sys_department`;

CREATE TABLE `sys_department` (

`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',

`department_key` varchar(20) NOT NULL COMMENT '部门编码',

`department_value` varchar(40) NOT NULL COMMENT '部门名称',

`description` varchar(200) DEFAULT NULL COMMENT '描述',

`parent_departmentkey` varchar(20) DEFAULT NULL COMMENT '上级部门编码',

`create_time` varchar(30) DEFAULT NULL COMMENT '创建时间',

PRIMARY KEY (`id`),

UNIQUE KEY `uk_sys_department_department_key` (`department_key`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='部门表';

-- ----------------------------

-- Records of sys_department

-- ----------------------------

-- ----------------------------

-- Table structure for sys_role

-- ----------------------------

DROP TABLE IF EXISTS `sys_role`;

CREATE TABLE `sys_role` (

`role_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',

`role_key` varchar(30) DEFAULT NULL COMMENT '角色编码',

`create_time` varchar(30) DEFAULT NULL COMMENT '创建时间',

`description` varchar(200) DEFAULT NULL COMMENT '描述',

`role_value` varchar(40) NOT NULL COMMENT '角色名称',

`company_id` bigint(20) DEFAULT NULL,

PRIMARY KEY (`role_id`)

) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COMMENT='角色表';

-- ----------------------------

-- Records of sys_role

-- ----------------------------

INSERT INTO `sys_role` VALUES ('1', 'ROLE_USER', null, null, '', null);

INSERT INTO `sys_role` VALUES ('2', 'ROLE_ADMIN', null, null, '', null);

-- ----------------------------

-- Table structure for sys_role_authority

-- ----------------------------

DROP TABLE IF EXISTS `sys_role_authority`;

CREATE TABLE `sys_role_authority` (

`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键编号自增长',

`menu_code` varchar(50) NOT NULL COMMENT '菜单编码',

`role_key` varchar(40) NOT NULL COMMENT '角色编码',

`menu_type` int(11) DEFAULT NULL COMMENT '菜单类型 1 导航 2 按钮',

PRIMARY KEY (`id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='角色菜单表';

-- ----------------------------

-- Records of sys_role_authority

-- ----------------------------

-- ----------------------------

-- Table structure for sys_role_permission

-- ----------------------------

DROP TABLE IF EXISTS `sys_role_permission`;

CREATE TABLE `sys_role_permission` (

`role_id` int(11) NOT NULL COMMENT '角色主键编号',

`permissions` varchar(1000) DEFAULT NULL COMMENT '按钮权限',

KEY `FK9q28ewrhntqeipl1t04kh1be7` (`role_id`),

CONSTRAINT `FK9q28ewrhntqeipl1t04kh1be7` FOREIGN KEY (`role_id`) REFERENCES `sys_role` (`role_id`),

CONSTRAINT `fk_sys_role_permission_role_id` FOREIGN KEY (`role_id`) REFERENCES `sys_role` (`role_id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='角色按钮权限表';

-- ----------------------------

-- Records of sys_role_permission

-- ----------------------------

-- ----------------------------

-- Table structure for sys_user

-- ----------------------------

DROP TABLE IF EXISTS `sys_user`;

CREATE TABLE `sys_user` (

`user_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',

`login_account` varchar(30) NOT NULL COMMENT '登录账号',

`login_pass` varchar(65) NOT NULL COMMENT '登录密码',

`user_name` varchar(20) DEFAULT NULL COMMENT '昵称',

`user_head` varchar(30) DEFAULT NULL COMMENT '头像',

`user_phone` varchar(20) DEFAULT NULL COMMENT '手机',

`user_email` varchar(30) DEFAULT NULL COMMENT '邮箱',

`user_sex` int(11) DEFAULT NULL COMMENT '性别',

`user_birthday` varchar(30) DEFAULT NULL COMMENT '生日',

`register_time` varchar(30) NOT NULL COMMENT '注册时间',

`department_key` varchar(20) DEFAULT NULL COMMENT '部门编码',

PRIMARY KEY (`user_id`),

UNIQUE KEY `uk_sys_user_login_account` (`login_account`)

) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 COMMENT='用户表';

-- ----------------------------

-- Records of sys_user

-- ----------------------------

INSERT INTO `sys_user` VALUES ('2', 'hzw2312', '63cbbfefc6a5f389ea64299134e989a9a378d1293cad8b5623331bf5d0e023a9', null, null, null, 'hzw2312@sina.com', null, null, '2017-01-18 14:39:23', null);

INSERT INTO `sys_user` VALUES ('3', 'hzw2312f', '63cbbfefc6a5f389ea64299134e989a9a378d1293cad8b5623331bf5d0e023a9', null, null, null, 'hzw23d12@sina.com', null, null, '2017-01-18 15:25:08', null);

INSERT INTO `sys_user` VALUES ('4', 'hhsykx', '63cbbfefc6a5f389ea64299134e989a9a378d1293cad8b5623331bf5d0e023a9', null, null, null, 'hhs2312@sina.com', null, null, '2017-01-18 15:25:47', null);

-- ----------------------------

-- Table structure for sys_user_role

-- ----------------------------

DROP TABLE IF EXISTS `sys_user_role`;

CREATE TABLE `sys_user_role` (

`user_id` bigint(20) NOT NULL COMMENT '用户编号',

`role_id` int(20) NOT NULL COMMENT '角色编号',

PRIMARY KEY (`user_id`,`role_id`),

KEY `FKhh52n8vd4ny9ff4x9fb8v65qx` (`role_id`),

CONSTRAINT `FKb40xxfch70f5qnyfw8yme1n1s` FOREIGN KEY (`user_id`) REFERENCES `sys_user` (`user_id`),

CONSTRAINT `FKhh52n8vd4ny9ff4x9fb8v65qx` FOREIGN KEY (`role_id`) REFERENCES `sys_role` (`role_id`),

CONSTRAINT `fk_sys_user_role_role_id` FOREIGN KEY (`role_id`) REFERENCES `sys_role` (`role_id`),

CONSTRAINT `fk_sys_user_role_user_id` FOREIGN KEY (`user_id`) REFERENCES `sys_user` (`user_id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户角色映射表';

-- ----------------------------

-- Records of sys_user_role

-- ----------------------------

INSERT INTO `sys_user_role` VALUES ('3', '1');

INSERT INTO `sys_user_role` VALUES ('4', '1');

INSERT INTO `sys_user_role` VALUES ('2', '2');

下面我们开始根据之前的框架集成shiro

首先在pom.xml添加shiro的支持,先在properties中声明一下要倒入的版本:

1.3.2

1.2

然后在是dependency的添加:

org.apache.shiro

shiro-all

${shiro.version}

commons-logging

commons-logging

${commons-logging.version}

下面是shiro的配置跟spring配置放在同级目录spring-shiro.xml:

xmlns:util="http://springframework.org/schema/util"

xmlns:aop="http://springframework.org/schema/aop"

xmlns:xsi="http://w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="

http://springframework.org/schema/beans http://springframework.org/schema/beans/spring-beans.xsd

http://springframework.org/schema/util http://springframework.org/schema/util/spring-util.xsd

http://springframework.org/schema/aop http://springframework.org/schema/aop/spring-aop.xsd">

class="org.apache.shiro.web.mgt.CookieRememberMeManager">

/static/** = anon

/login.jsp = anon

/sysuser/login.action = anon

/sysuser/register.action = anon

/sysuser/getEMailCount.action = anon

/sysuser/getUserNameCount.action = anon

/sysuser/logout.action = logout

/** = user,sysUser

xmlns:util="http://springframework.org/schema/util"

xmlns:aop="http://springframework.org/schema/aop"

xmlns:xsi="http://w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="

http://springframework.org/schema/beans http://springframework.org/schema/beans/spring-beans.xsd

http://springframework.org/schema/util http://springframework.org/schema/util/spring-util.xsd

http://springframework.org/schema/aop http://springframework.org/schema/aop/spring-aop.xsd">

class="org.apache.shiro.web.mgt.CookieRememberMeManager">

class="org.apache.shiro.web.mgt.CookieRememberMeManager">

/static/** = anon

/login.jsp = anon

/sysuser/login.action = anon

/sysuser/register.action = anon

/sysuser/getEMailCount.action = anon

/sysuser/getUserNameCount.action = anon

/sysuser/logout.action = logout

/** = user,sysUser

上面的

/static/** = anon,/login.jsp = anon...这些等于anon的就是默认不做权限验证的,我们的登录,注册,静态资源等,不需要权限验证。

权限缓存的配置(如果不用缓存的话,每次请求都要去访问数据库查询权限)ehcache-shiro.xml:

overflowToDisk="true" timeToIdleSeconds="300" timeToLiveSeconds="180"

diskPersistent="false" diskExpiryThreadIntervalSeconds="120" />

maxEntriesLocalHeap="2000"

eternal="false"

timeToIdleSeconds="3600"

timeToLiveSeconds="0"

overflowToDisk="false"

statistics="true">

maxEntriesLocalHeap="2000"

eternal="false"

timeToIdleSeconds="3600"

timeToLiveSeconds="0"

overflowToDisk="false"

statistics="true">

maxEntriesLocalHeap="2000"

eternal="false"

timeToIdleSeconds="3600"

timeToLiveSeconds="0"

overflowToDisk="false"

statistics="true">

maxEntriesLocalHeap="2000"

eternal="false"

timeToIdleSeconds="3600"

timeToLiveSeconds="0"

overflowToDisk="false"

statistics="true">

maxEntriesLocalHeap="2000"

eternal="false"

timeToIdleSeconds="3600"

timeToLiveSeconds="0"

overflowToDisk="false"

statistics="true">

自定义用户过滤类SysUserFilter:

import yfkj.gz.task.service.ISysUserService;

import org.apache.shiro.web.filter.PathMatchingFilter;

import javax.annotation.Resource;

import javax.servlet.ServletRequest;

import javax.servlet.ServletResponse;

/**

* 自定义用户过滤器

* @author 胡汉三

*

*/

public class SysUserFilter extends PathMatchingFilter {

@Resource

private ISysUserService sysUserService;

@Override

protected boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {

//可以参考http://jinnianshilongnian.iteye.com/blog/2025656

return true;

}

}

权限认证类ShiroSecurityRealm:

import javax.annotation.Resource;

import org.apache.shiro.authc.AuthenticationException;

import org.apache.shiro.authc.AuthenticationInfo;

import org.apache.shiro.authc.AuthenticationToken;

import org.apache.shiro.authc.SimpleAuthenticationInfo;

import org.apache.shiro.authc.UsernamePasswordToken;

import org.apache.shiro.authc.credential.Sha256CredentialsMatcher;

import org.apache.shiro.authz.AuthorizationInfo;

import org.apache.shiro.authz.SimpleAuthorizationInfo;

import org.apache.shiro.realm.AuthorizingRealm;

import org.apache.shiro.subject.PrincipalCollection;

import org.springframework.stereotype.Component;

import yfkj.gz.task.dao.ISysUserDao;

import yfkj.gz.task.entity.SysRole;

import yfkj.gz.task.entity.SysUser;

import yfkj.gz.task.service.ISysUserService;

/**

* 权限认证

* @author 胡汉三

* @date 2017年1月19日 上午10:52:17

*/

@SuppressWarnings("deprecation")

@Component

public class ShiroSecurityRealm extends AuthorizingRealm {

@Resource

private ISysUserService userService;

@Resource

private ISysUserDao sysUserDao;

public ShiroSecurityRealm() {

setName("ShiroSecurityRealm"); // This name must match the name in the SysUser class's getPrincipals() method

setCredentialsMatcher(new Sha256CredentialsMatcher());

hJlsuxw}

/**

* 登录认证

*/

protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {

UsernamePasswordToken token = (UsernamePasswordToken) authcToken;

SysUser user = userService.getByProerties(new String[]{"loginAccount"}, new String[]{token.getUsername()},null);

if (user != null) {

return new SimpleAuthenticationInfo(user.getUserId(), user.getLoginPass(), getName());

} else {

return null;

}

}

/**

* 权限认证

*/

protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

Long userId = (Long) principals.fromRealm(getName()).iterator().next();

SysUser user = userService.get(userId);

if (user != null) {

SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

for (SysRole role : user.getRoles()) {

info.addRole(role.getRoleKey());

info.addStringPermissions(role.getPermissions());

}

return info;

} else {

return null;

}

}

}

在web.xml加入:

contextConfigLocation

classpath:spring.xml,classpath:spring-hibernate.xml,classpath:spring-shiro.xml

shiroFilter

org.springframework.web.filter.DelegatingFilterProxy

targetFilterLifecycle

true

shiroFilter

/*

在登录方法中加上权限的登录(构造方法参数:登录账号,登录密码,记住我):

//存入session

Subject subject = SecurityUtils.getSubject();

//记得传入明文密码

subject.login(new UsernamePasswordToken(userInfo.getLoginAccount(), user.getLoginPass(), rememberMe));

完整的登录方法:

[java] view plain copy 在CODE上查看代码片派生到我的代码片

/**

* 用户登录

* @param response

* @param user

* @throws IOException

*/

@RequestMapping(value = "/login", method = { RequestMethod.POST, RequestMethod.GET })

public void login(SysUser user,boolean rememberMe) throws IOException{

//用户登录

SysUser userInfo = userService.getByProerties(new String[]{"loginAccount"}, new String[]{user.getLoginAccount()},null);

if(userInfo==null){

result.setMessage("用户名错误");

super.writeJSON(result);

return;

}

if(!userInfo.getLoginPass().equals(new Sha256Hash(user.getLoginPass()).toHex())){

result.setMessage("密码错误");

super.writeJSON(result);

return;

}

//存入session

Subject subject = SecurityUtils.getSubject();

//记得传入明文密码

subject.login(new UsernamePasswordToken(userInfo.getLoginAccount(), user.getLoginPass(), rememberMe));

session.setAttribute(USER_SESSION, userInfo);

result.setMessage("登录成功");

result.setSuccess(true);

super.writeJSON(result);

}

数据库也设计好啦,该整合的也整合了,怎么来实现呢,这里先说一点点,详细的等下一篇说:

jsp页面引入page指令:

<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>

在要做验证的按钮上加上shiro标签的判断:

新增

${ROLE_KEY}:role:role_add的意思就是:

${ROLE_KEY}角色

role是指菜单(页面)

role_add指的功能

联合起来就是,当前角色在role菜单(页面)中有没有role_add新增的功能,如果有就会显示,没有就不显示这个按钮啦。

在后台方法中验证:

在对应的方法中加入代码:

Subject subject = SecurityUtils.getSubject();

subject.checkPermission(getCurrentRoleKey()+":role:role_add");

如果没有通过checkPermission,则会直接返回错误,不执行下面的代码啦。

实体Base类BaseEntity:

import java.io.Serializable;

import java.util.LinkedHashMap;

import java.util.Map;

/**

* 实体父类

* @author 胡汉三

* @date 2017年1月18日 上午11:03:11

*/

public class BaseEntity implements Serializable{

/**

*

*/

private static final long serialVersionUID = 3730369554400423966L;

/**

* 排序

*/

private Map sortedConditions = new LinkedHashMap();

public Map getSortedConditions() {

return sortedConditions;

}

public void setSortedConditions(Map sortedConditions) {

this.sortedConditions = sortedConditions;

}

}

用户实体SysUser:

import java.util.HashSet;

import java.util.Set;

import javax.persistence.Column;

import javax.persistence.Entity;

import javax.persistence.FetchType;

import javax.persistence.GeneratedValue;

import javax.persistence.Id;

import javax.persistence.JoinTable;

import javax.persistence.JoinColumn;

import javax.persistence.ManyToMany;

import javax.persistence.Table;

import org.hibernate.annotations.Cache;

import org.hibernate.annotations.CacheConcurrencyStrategy;

import yfkj.gz.support.BaseEntity;

/**

* 用户的实体类

*/

@Entity

@Table(name = "sys_user")

public class SysUser extends BaseEntity{

/**

*

*/

private static final long serialVersionUID = 2491111485758197830L;

/**主键**/

@Id

@GeneratedValue

@Column(name = "user_id")

private Long userId;

/**登录账号**/

@Column(name = "login_account" ,length = 30 , unique = true )

private String loginAccount;

/**登录密码**/

@Column(name = "login_pass" ,length = 65)

private String loginPass;

/**昵称**/

@Column(name = "user_name" ,length = 20)

private String userName;

/**头像**/

@Column(name = "user_head" ,length = 30)

private String userHead;

/**手机**/

@Column(name = "user_phone" ,length = 20)

private String userPhone;

/**邮箱**/

@Column(name = "user_email" ,length = 30)

private String userEmail;

/**性别**/

@Column(name = "user_sex")

private Integer userSex;

/**生日**/

@Column(name = "user_birthday" ,length = 30)

private String userBirthday;

/**注册时间**/

@Column(name = "register_time" ,length = 30)

private String registerTime;

/**部门编码**/

@Column(name = "department_key" ,length = 20)

private String departmentKey;

/**用户角色**/

@ManyToMany(fetch = FetchType.EAGER)

@JoinTable(name = "sys_user_role", joinColumns = { @JoinColumn(name = "user_id") }, inverseJoinColumns = { @JoinColumn(name = "role_id") })

@Cache(region = "all", usage = CacheConcurrencyStrategy.READ_WRITE)

private Set roles = new HashSet();

/**get/set**/

/**主键**/

public Long getUserId(){

return userId;

}

/**主键**/

public void setUserId(Long userId){

this.userId= userId;

}

/**登录账号**/

public String getLoginAccount(){

return loginAccount;

}

/**登录账号**/

public void setLoginAccount(String loginAccount){

this.loginAccount= loginAccount;

}

/**登录密码**/

public String getLoginPass(){

return loginPass;

}

/**登录密码**/

public void setLoginPass(String loginPass){

this.loginPass= loginPass;

}

/**昵称**/

public String getUserName(){

return userName;

}

/**昵称**/

public void setUserName(String userName){

this.userName= userName;

}

/**头像**/

public String getUserHead(){

return userHead;

}

/**头像**/

public void setUserHead(String userHead){

this.userHead= userHead;

}

/**手机**/

public String getUserPhone(){

return userPhone;

}

/**手机**/

public void setUserPhone(String userPhone){

this.userPhone= userPhone;

}

/**邮箱**/

public String getUserEmail(){

return userEmail;

}

/**邮箱**/

public void setUserEmail(String userEmail){

this.userEmail= userEmail;

}

/**性别**/

public Integer getUserSex(){

return userSex;

}

/**性别**/

public void setUserSex(Integer userSex){

this.userSex= userSex;

}

/**生日**/

public String getUserBirthday(){

return userBirthday;

}

/**生日**/

public void setUserBirthday(String userBirthday){

this.userBirthday= userBirthday;

}

/**注册时间**/

public String getRegisterTime(){

return registerTime;

}

/**注册时间**/

public void setRegisterTime(String registerTime){

this.registerTime= registerTime;

}

public Set getRoles() {

return roles;

}

public void setRoles(Set roles) {

this.roles = roles;

}

}

角色实体SysRole:

import java.util.Set;

import javax.persistence.Column;

import javax.persistence.ElementCollection;

import javax.persistence.Entity;

import javax.persistence.GeneratedValue;

import javax.persistence.Id;

import javax.persistence.JoinColumn;

import javax.persistence.JoinTable;

import javax.persistence.Table;

import org.hibernate.annotations.Cache;

import org.hibernate.annotations.CacheConcurrencyStrategy;

import yfkj.gz.support.BaseEntity;

/**

* 角色的实体类

*/

@Entity

@Table(name = "sys_role")

@Cache(region = "all", usage = CacheConcurrencyStrategy.READ_WRITE)

public class SysRole extends BaseEntity{

// 各个字段的含义请查阅文档的数据库结构部分

private static final long serialVersionUID = 6019103858711599150L;

@Id

@GeneratedValue

@Column(name = "role_id")

private Long roleId;

@Column(name = "role_key", length = 40, nullable = false, unique = true)

private String roleKey;

@Column(name = "role_value", length = 40, nullable = false)

private String roleValue;

@Column(name = "create_time", length = 30)

private String createTime;

@Column(name = "description", length = 200)

private String description;

@ElementCollection

@JoinTable(name = "sys_role_permission", joinColumns = { @JoinColumn(name = "role_id") })

@Cache(region = "all", usage = CacheConcurrencyStrategy.READ_WRITE)

private Set permissions;

@Column(name="company_id")

private Long companyId;

public SysRole() {

}

public Long getRoleId() {

return roleId;

}

public void setRoleId(Long roleId) {

this.roleId = roleId;

}

public String getRoleKey() {

return roleKey;

}

public void setRoleKey(String roleKey) {

this.roleKey = roleKey;

}

public String getRoleValue() {

return roleValue;

}

public void setRoleValue(String roleValue) {

this.roleValue = roleValue;

}

public String getCreateTime() {

return createTime;

}

public void setCreateTime(String createTime) {

this.createTime = createTime;

}

public String getDescription() {

return description;

}

public void setDescription(String description) {

this.description = description;

}

public Set getPermissions() {

return permissions;

}

public void setPermissions(Set permissions) {

this.permissions = permissions;

}

public Long getCompanyId() {

return companyId;

}

public void setCompanyId(Long companyId) {

this.companyId = companyId;

}

}

项目结构图:

源码地址:spring-shiro_jb51.rar

overflowToDisk="true" timeToIdleSeconds="300" timeToLiveSeconds="180"

diskPersistent="false" diskExpiryThreadIntervalSeconds="120" />

maxEntriesLocalHeap="2000"

eternal="false"

timeToIdleSeconds="3600"

timeToLiveSeconds="0"

overflowToDisk="false"

statistics="true">

maxEntriesLocalHeap="2000"

eternal="false"

timeToIdleSeconds="3600"

timeToLiveSeconds="0"

overflowToDisk="false"

statistics="true">

maxEntriesLocalHeap="2000"

eternal="false"

timeToIdleSeconds="3600"

timeToLiveSeconds="0"

overflowToDisk="false"

statistics="true">

maxEntriesLocalHeap="2000"

eternal="false"

timeToIdleSeconds="3600"

timeToLiveSeconds="0"

overflowToDisk="false"

statistics="true">

maxEntriesLocalHeap="2000"

eternal="false"

timeToIdleSeconds="3600"

timeToLiveSeconds="0"

overflowToDisk="false"

statistics="true">

maxEntriesLocalHeap="2000"

eternal="false"

timeToIdleSeconds="3600"

timeToLiveSeconds="0"

overflowToDisk="false"

statistics="true">

maxEntriesLocalHeap="2000"

eternal="false"

timeToIdleSeconds="3600"

timeToLiveSeconds="0"

overflowToDisk="false"

statistics="true">

maxEntriesLocalHeap="2000"

eternal="false"

timeToIdleSeconds="3600"

timeToLiveSeconds="0"

overflowToDisk="false"

statistics="true">

maxEntriesLocalHeap="2000"

eternal="false"

timeToIdleSeconds="3600"

timeToLiveSeconds="0"

overflowToDisk="false"

statistics="true">

maxEntriesLocalHeap="2000"

eternal="false"

timeToIdleSeconds="3600"

timeToLiveSeconds="0"

overflowToDisk="false"

statistics="true">

自定义用户过滤类SysUserFilter:

import yfkj.gz.task.service.ISysUserService;

import org.apache.shiro.web.filter.PathMatchingFilter;

import javax.annotation.Resource;

import javax.servlet.ServletRequest;

import javax.servlet.ServletResponse;

/**

* 自定义用户过滤器

* @author 胡汉三

*

*/

public class SysUserFilter extends PathMatchingFilter {

@Resource

private ISysUserService sysUserService;

@Override

protected boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {

//可以参考http://jinnianshilongnian.iteye.com/blog/2025656

return true;

}

}

权限认证类ShiroSecurityRealm:

import javax.annotation.Resource;

import org.apache.shiro.authc.AuthenticationException;

import org.apache.shiro.authc.AuthenticationInfo;

import org.apache.shiro.authc.AuthenticationToken;

import org.apache.shiro.authc.SimpleAuthenticationInfo;

import org.apache.shiro.authc.UsernamePasswordToken;

import org.apache.shiro.authc.credential.Sha256CredentialsMatcher;

import org.apache.shiro.authz.AuthorizationInfo;

import org.apache.shiro.authz.SimpleAuthorizationInfo;

import org.apache.shiro.realm.AuthorizingRealm;

import org.apache.shiro.subject.PrincipalCollection;

import org.springframework.stereotype.Component;

import yfkj.gz.task.dao.ISysUserDao;

import yfkj.gz.task.entity.SysRole;

import yfkj.gz.task.entity.SysUser;

import yfkj.gz.task.service.ISysUserService;

/**

* 权限认证

* @author 胡汉三

* @date 2017年1月19日 上午10:52:17

*/

@SuppressWarnings("deprecation")

@Component

public class ShiroSecurityRealm extends AuthorizingRealm {

@Resource

private ISysUserService userService;

@Resource

private ISysUserDao sysUserDao;

public ShiroSecurityRealm() {

setName("ShiroSecurityRealm"); // This name must match the name in the SysUser class's getPrincipals() method

setCredentialsMatcher(new Sha256CredentialsMatcher());

hJlsuxw}

/**

* 登录认证

*/

protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {

UsernamePasswordToken token = (UsernamePasswordToken) authcToken;

SysUser user = userService.getByProerties(new String[]{"loginAccount"}, new String[]{token.getUsername()},null);

if (user != null) {

return new SimpleAuthenticationInfo(user.getUserId(), user.getLoginPass(), getName());

} else {

return null;

}

}

/**

* 权限认证

*/

protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

Long userId = (Long) principals.fromRealm(getName()).iterator().next();

SysUser user = userService.get(userId);

if (user != null) {

SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

for (SysRole role : user.getRoles()) {

info.addRole(role.getRoleKey());

info.addStringPermissions(role.getPermissions());

}

return info;

} else {

return null;

}

}

}

在web.xml加入:

contextConfigLocation

classpath:spring.xml,classpath:spring-hibernate.xml,classpath:spring-shiro.xml

shiroFilter

org.springframework.web.filter.DelegatingFilterProxy

targetFilterLifecycle

true

shiroFilter

/*

在登录方法中加上权限的登录(构造方法参数:登录账号,登录密码,记住我):

//存入session

Subject subject = SecurityUtils.getSubject();

//记得传入明文密码

subject.login(new UsernamePasswordToken(userInfo.getLoginAccount(), user.getLoginPass(), rememberMe));

完整的登录方法:

[java] view plain copy 在CODE上查看代码片派生到我的代码片

/**

* 用户登录

* @param response

* @param user

* @throws IOException

*/

@RequestMapping(value = "/login", method = { RequestMethod.POST, RequestMethod.GET })

public void login(SysUser user,boolean rememberMe) throws IOException{

//用户登录

SysUser userInfo = userService.getByProerties(new String[]{"loginAccount"}, new String[]{user.getLoginAccount()},null);

if(userInfo==null){

result.setMessage("用户名错误");

super.writeJSON(result);

return;

}

if(!userInfo.getLoginPass().equals(new Sha256Hash(user.getLoginPass()).toHex())){

result.setMessage("密码错误");

super.writeJSON(result);

return;

}

//存入session

Subject subject = SecurityUtils.getSubject();

//记得传入明文密码

subject.login(new UsernamePasswordToken(userInfo.getLoginAccount(), user.getLoginPass(), rememberMe));

session.setAttribute(USER_SESSION, userInfo);

result.setMessage("登录成功");

result.setSuccess(true);

super.writeJSON(result);

}

数据库也设计好啦,该整合的也整合了,怎么来实现呢,这里先说一点点,详细的等下一篇说:

jsp页面引入page指令:

<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>

在要做验证的按钮上加上shiro标签的判断:

新增

${ROLE_KEY}:role:role_add的意思就是:

${ROLE_KEY}角色

role是指菜单(页面)

role_add指的功能

联合起来就是,当前角色在role菜单(页面)中有没有role_add新增的功能,如果有就会显示,没有就不显示这个按钮啦。

在后台方法中验证:

在对应的方法中加入代码:

Subject subject = SecurityUtils.getSubject();

subject.checkPermission(getCurrentRoleKey()+":role:role_add");

如果没有通过checkPermission,则会直接返回错误,不执行下面的代码啦。

实体Base类BaseEntity:

import java.io.Serializable;

import java.util.LinkedHashMap;

import java.util.Map;

/**

* 实体父类

* @author 胡汉三

* @date 2017年1月18日 上午11:03:11

*/

public class BaseEntity implements Serializable{

/**

*

*/

private static final long serialVersionUID = 3730369554400423966L;

/**

* 排序

*/

private Map sortedConditions = new LinkedHashMap();

public Map getSortedConditions() {

return sortedConditions;

}

public void setSortedConditions(Map sortedConditions) {

this.sortedConditions = sortedConditions;

}

}

用户实体SysUser:

import java.util.HashSet;

import java.util.Set;

import javax.persistence.Column;

import javax.persistence.Entity;

import javax.persistence.FetchType;

import javax.persistence.GeneratedValue;

import javax.persistence.Id;

import javax.persistence.JoinTable;

import javax.persistence.JoinColumn;

import javax.persistence.ManyToMany;

import javax.persistence.Table;

import org.hibernate.annotations.Cache;

import org.hibernate.annotations.CacheConcurrencyStrategy;

import yfkj.gz.support.BaseEntity;

/**

* 用户的实体类

*/

@Entity

@Table(name = "sys_user")

public class SysUser extends BaseEntity{

/**

*

*/

private static final long serialVersionUID = 2491111485758197830L;

/**主键**/

@Id

@GeneratedValue

@Column(name = "user_id")

private Long userId;

/**登录账号**/

@Column(name = "login_account" ,length = 30 , unique = true )

private String loginAccount;

/**登录密码**/

@Column(name = "login_pass" ,length = 65)

private String loginPass;

/**昵称**/

@Column(name = "user_name" ,length = 20)

private String userName;

/**头像**/

@Column(name = "user_head" ,length = 30)

private String userHead;

/**手机**/

@Column(name = "user_phone" ,length = 20)

private String userPhone;

/**邮箱**/

@Column(name = "user_email" ,length = 30)

private String userEmail;

/**性别**/

@Column(name = "user_sex")

private Integer userSex;

/**生日**/

@Column(name = "user_birthday" ,length = 30)

private String userBirthday;

/**注册时间**/

@Column(name = "register_time" ,length = 30)

private String registerTime;

/**部门编码**/

@Column(name = "department_key" ,length = 20)

private String departmentKey;

/**用户角色**/

@ManyToMany(fetch = FetchType.EAGER)

@JoinTable(name = "sys_user_role", joinColumns = { @JoinColumn(name = "user_id") }, inverseJoinColumns = { @JoinColumn(name = "role_id") })

@Cache(region = "all", usage = CacheConcurrencyStrategy.READ_WRITE)

private Set roles = new HashSet();

/**get/set**/

/**主键**/

public Long getUserId(){

return userId;

}

/**主键**/

public void setUserId(Long userId){

this.userId= userId;

}

/**登录账号**/

public String getLoginAccount(){

return loginAccount;

}

/**登录账号**/

public void setLoginAccount(String loginAccount){

this.loginAccount= loginAccount;

}

/**登录密码**/

public String getLoginPass(){

return loginPass;

}

/**登录密码**/

public void setLoginPass(String loginPass){

this.loginPass= loginPass;

}

/**昵称**/

public String getUserName(){

return userName;

}

/**昵称**/

public void setUserName(String userName){

this.userName= userName;

}

/**头像**/

public String getUserHead(){

return userHead;

}

/**头像**/

public void setUserHead(String userHead){

this.userHead= userHead;

}

/**手机**/

public String getUserPhone(){

return userPhone;

}

/**手机**/

public void setUserPhone(String userPhone){

this.userPhone= userPhone;

}

/**邮箱**/

public String getUserEmail(){

return userEmail;

}

/**邮箱**/

public void setUserEmail(String userEmail){

this.userEmail= userEmail;

}

/**性别**/

public Integer getUserSex(){

return userSex;

}

/**性别**/

public void setUserSex(Integer userSex){

this.userSex= userSex;

}

/**生日**/

public String getUserBirthday(){

return userBirthday;

}

/**生日**/

public void setUserBirthday(String userBirthday){

this.userBirthday= userBirthday;

}

/**注册时间**/

public String getRegisterTime(){

return registerTime;

}

/**注册时间**/

public void setRegisterTime(String registerTime){

this.registerTime= registerTime;

}

public Set getRoles() {

return roles;

}

public void setRoles(Set roles) {

this.roles = roles;

}

}

角色实体SysRole:

import java.util.Set;

import javax.persistence.Column;

import javax.persistence.ElementCollection;

import javax.persistence.Entity;

import javax.persistence.GeneratedValue;

import javax.persistence.Id;

import javax.persistence.JoinColumn;

import javax.persistence.JoinTable;

import javax.persistence.Table;

import org.hibernate.annotations.Cache;

import org.hibernate.annotations.CacheConcurrencyStrategy;

import yfkj.gz.support.BaseEntity;

/**

* 角色的实体类

*/

@Entity

@Table(name = "sys_role")

@Cache(region = "all", usage = CacheConcurrencyStrategy.READ_WRITE)

public class SysRole extends BaseEntity{

// 各个字段的含义请查阅文档的数据库结构部分

private static final long serialVersionUID = 6019103858711599150L;

@Id

@GeneratedValue

@Column(name = "role_id")

private Long roleId;

@Column(name = "role_key", length = 40, nullable = false, unique = true)

private String roleKey;

@Column(name = "role_value", length = 40, nullable = false)

private String roleValue;

@Column(name = "create_time", length = 30)

private String createTime;

@Column(name = "description", length = 200)

private String description;

@ElementCollection

@JoinTable(name = "sys_role_permission", joinColumns = { @JoinColumn(name = "role_id") })

@Cache(region = "all", usage = CacheConcurrencyStrategy.READ_WRITE)

private Set permissions;

@Column(name="company_id")

private Long companyId;

public SysRole() {

}

public Long getRoleId() {

return roleId;

}

public void setRoleId(Long roleId) {

this.roleId = roleId;

}

public String getRoleKey() {

return roleKey;

}

public void setRoleKey(String roleKey) {

this.roleKey = roleKey;

}

public String getRoleValue() {

return roleValue;

}

public void setRoleValue(String roleValue) {

this.roleValue = roleValue;

}

public String getCreateTime() {

return createTime;

}

public void setCreateTime(String createTime) {

this.createTime = createTime;

}

public String getDescription() {

return description;

}

public void setDescription(String description) {

this.description = description;

}

public Set getPermissions() {

return permissions;

}

public void setPermissions(Set permissions) {

this.permissions = permissions;

}

public Long getCompanyId() {

return companyId;

}

public void setCompanyId(Long companyId) {

this.companyId = companyId;

}

}

项目结构图:

源码地址:spring-shiro_jb51.rar


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:接口继承与实现继承(接口继承和实现的区别)
下一篇:angular directive的简单使用总结
相关文章

 发表评论

暂时没有评论,来抢沙发吧~