`
sdh88hf
  • 浏览: 67800 次
  • 性别: Icon_minigender_1
  • 来自: 绍兴
社区版块
存档分类
最新评论

Web开发学习7按钮级别权限控制

阅读更多
这个功能的思路是自己原创的,没看过其他例子,其实是在做之前网上搜了很多也没个可以参考的例子.主要技术是后台springsecurity做拦截判断,前台Extjs4做按钮动态渲染.如果你不了解springsecrity,那你可以先看下我的另一篇相关博客

创建数据库表(liqiubase方式创建看上一篇)


 <createTable tableName="permissions">  
            <column name="id" type="bigint">  
                <constraints nullable="false" primaryKey="true" />  
            </column>  
            <!-- 权限名称 -->
            <column name="name" type="varchar(32)" />
            <!-- 该权限需要访问的链接 -->
            <column name="actionurl" type="varchar(256)" /> 
            <!-- 该权限需要用到的js -->
            <column name="jsurl" type="varchar(256)" />
            <!-- 权限等级 1主菜单 2子菜单 3及以下按钮 -->
            <column name="level" type="int" />
            <!-- 菜单父级id -->
            <column name="parentid" type="bigint"/>
            <!-- 排序编号 -->
            <column name="ordernum" type="int" defaultValue="0"/>  
        </createTable>

这张是权限表,也是菜单(按钮)表,每个菜单都有他自己需要访问链接的权限,当菜单类型为子菜单或按钮时还需要配置该按钮对应的js文件,对没错,每个按钮都有自己独立的js文件,在用户没有按钮权限的时候,前端是js都不需要加载的

添加菜单初始数据


<insert tableName="permissions">
        	<column name="id" value="1"/>  
            <column name="name" value="用户管理" />
            <column name="level" value="1" />
            <column name="parentid" value="-1"/>
            <column name="ordernum" value="1"/>
        </insert>
        <insert tableName="permissions">
        	<column name="id" value="101"/>  
            <column name="name" value="账号管理" />
            <column name="actionurl" value="account!query.action" /> 
            <column name="jsurl" value="user/account/searchGrid" />
            <column name="level" value="2" />
            <column name="parentid" value="1"/>
            <column name="ordernum" value="1"/>
        </insert>
        <insert tableName="permissions">
        	<column name="id" value="102"/>  
            <column name="name" value="角色管理" />
            <column name="actionurl" value="" /> 
            <column name="jsurl" value="user/role/mainPanel" />
            <column name="level" value="2" />
            <column name="parentid" value="1"/>
            <column name="ordernum" value="2"/>
        </insert>
        <insert tableName="permissions">
        	<column name="id" value="1001"/>  
            <column name="name" value="新增" />
            <column name="actionurl" value="account!save.action" /> 
            <column name="jsurl" value="user/account/searchGridAddBtn" />
            <column name="level" value="3" />
            <column name="parentid" value="101"/>
            <column name="ordernum" value="1"/>
        </insert>
        <insert tableName="permissions">
        	<column name="id" value="1004"/>  
            <column name="name" value="修改" />
            <column name="actionurl"   value="account!save.action,account!find.action" /> 
            <column name="jsurl" value="user/account/searchGridUpdBtn" />
            <column name="level" value="3" />
            <column name="parentid" value="101"/>
            <column name="ordernum" value="1"/>
        </insert>


添加了一个父级菜单用户管理,两个子集菜单账号管理和角色管理,同时在账号管理下添加两个按钮新增和修改,需要注意的是新增的授权链接是account!save.action而修改的授权链接是account!save.action,account!find.action,因为修改需要先查再能改,当用户被授予新增和修改两个权限的时候,访问account!save.action,account!find.action也就不会受阻了

创建角色表和角色权限关联表

<createTable tableName="roles">  
        	<column name="id" type="bigint">  
                <constraints nullable="false" primaryKey="true" />  
            </column>
            <column name="rolename" type="varchar(32)" />
		</createTable>
		
		<insert tableName="roles">  
            <column name="id" value="1" />  
            <column name="rolename" value="超级管理员" />  
        </insert>
<createTable tableName="role_permission">  
            <column name="id" type="bigint">  
                <constraints nullable="false" primaryKey="true" />  
            </column>  
            <column name="perid" type="bigint" />
            <column name="roleid" type="bigint" /> 
        </createTable>


角色和权限是多对多的关系,一个角色可以有多个权限,一个权限也可以属于多个角色,
配完初始数据以后前台展示大致是这样的(图片太大请在新窗口打开)




拥有角色管理的的用户可以添加删除角色,同时可以为没每个角色分配权限
创建用户角色关联表

<createTable tableName="account_role">  
            <column name="accountid" type="bigint" />
            <column name="roleid" type="bigint" /> 
        </createTable>
        <insert tableName="account_role">
            <column name="accountid" value="1" />
            <column name="roleid" value="1" /> 
        </insert>


这里给admin初始化了id为1的角色,也就是超级管理员,同样
拥有账号管理里的用户可以为账号添加角色


到这里数据的配置基本讲完了,再展示下初始数据的liqiubase文件,大致就是那几张表,
最后我再给游客2分配了几个权限,新增一个角色为游客2的账号









以上展示的只是数据配置的过程,通俗的讲就是想法,
现在想法已经出来了,权限也分配好了真正的权限控制核心代码就开始了,首先展示下我的hibernate entity

package cn.sdh.entity;

import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Transient;

import org.apache.struts2.json.annotations.JSON;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.GrantedAuthorityImpl;
import org.springframework.security.core.userdetails.UserDetails;

import cn.sdh.common.base.AuditEntity;

@SuppressWarnings("serial")
@Entity
@Table(name="accounts")
public class Account extends AuditEntity implements UserDetails {

	
	public Account(){
	}
	
	public Account(Long id, String username, String password, String email,Date lastLoginTime, int userType){
		this.id = id;
		this.username = username;
		this.password = password;
		this.email = email;
		this.lastLoginTime = lastLoginTime;
		this.userType = userType;
	}
	
	@Id
	@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_ACCOUNT")
	@SequenceGenerator(name = "SEQ_ACCOUNT", sequenceName = "SEQ_ACCOUNT", initialValue = 2, allocationSize = 1)
	@Column(name="id")
	private Long id;
	
	@Column(name="username")
	private String username;
	
	@Column(name="password")
	private String password;
	
	@Column(name="email")
	private String email;
	
	//@Type(type="cn.sdh.common.userType.dateToInt")
	@Column(name="lastlogintime")
	private Date lastLoginTime;
	
	private int userType;//用户类型-1:超级管理员 0普通用户 1+级用户
	
	//是否在线
	@Transient
	private int isOnLine;
	
	//搜索时间 起止
	@Transient
	private Date lastLoginTime1;
	
	@Transient
	private Date lastLoginTime2;
	
	@ManyToMany(fetch = FetchType.EAGER)
	@JoinTable(name="account_role",joinColumns={@JoinColumn(name="accountid")},inverseJoinColumns={@JoinColumn(name="roleid")})
	private List<Role> roles = new ArrayList<Role>();
	
	@Transient
	private File photo;

	public Long getId() {
		return id;
	}

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

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public List<Role> getRoles() {
		return roles;
	}

	public void setRoles(List<Role> roles) {
		this.roles = roles;
	}

	public Date getLastLoginTime() {
		return lastLoginTime;
	}

	public void setLastLoginTime(Date lastLoginTime) {
		this.lastLoginTime = lastLoginTime;
	}

	/**
	 * 告诉spring当前用户的角色
	 */
	@Override
	@JSON(serialize=false)
	public Collection<GrantedAuthority> getAuthorities() {
		Set<GrantedAuthority> authSet = new HashSet<GrantedAuthority>();
		for (Role role : this.getRoles()) {
			authSet.add(new GrantedAuthorityImpl(role.getId().toString()));
		}
		return authSet;
	}

	@Override
	@JSON(serialize=false)
	public boolean isAccountNonExpired() {
		return true;
	}

	@Override
	@JSON(serialize=false)
	public boolean isAccountNonLocked() {
		return true;
	}

	@Override
	@JSON(serialize=false)
	public boolean isCredentialsNonExpired() {
		return true;
	}

	@Override
	@JSON(serialize=false)
	public boolean isEnabled() {
		return true;
	}

	public Date getLastLoginTime1() {
		return lastLoginTime1;
	}

	public void setLastLoginTime1(Date lastLoginTime1) {
		this.lastLoginTime1 = lastLoginTime1;
	}

	public Date getLastLoginTime2() {
		return lastLoginTime2;
	}

	public void setLastLoginTime2(Date lastLoginTime2) {
		this.lastLoginTime2 = lastLoginTime2;
	}

	public int getUserType() {
		return userType;
	}

	public void setUserType(int userType) {
		this.userType = userType;
	}
	
	public int getIsOnLine() {
		return isOnLine;
	}

	public void setIsOnLine(int isOnLine) {
		this.isOnLine = isOnLine;
	}
	
	@JSON(serialize=false)
	public List<Permission> getSignPer(){
		
		List<Permission> perList = new ArrayList<Permission>();
		
		for(Role role : this.getRoles()){
			List<Permission> sublist = role.getPermissionList();
			
			for(int h = 0; h<sublist.size(); h++){
				boolean continueFlag = false;
				
				for(int j = 0;j<perList.size();j++){
					if(role.getPermissionList().get(h).getId()==perList.get(j).getId()){
						continueFlag = true;
						
						break;
					}
					
				}
				
				if(continueFlag){
					continue;
				}
				if(role.getPermissionList().get(h).getLevel()==2){
					role.getPermissionList().get(h).setLeaf(1);
				}
				role.getPermissionList().get(h).setChildren(null);
				//role.getPermissionList().get(h).setControlType(role.getPermissionList().get(h).getControlType());
				perList.add(role.getPermissionList().get(h));
			}
			
		}
		
		return perList;
	}

	public File getPhoto() {
		return photo;
	}

	public void setPhoto(File photo) {
		this.photo = photo;
	}
	
}


package cn.sdh.entity;

import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Transient;

import org.apache.struts2.json.annotations.JSON;

import cn.sdh.common.base.AuditEntity;

/**
 * 权限类(菜单,按钮,功能)
 * @author 孙东辉
 */
@Entity
@Table(name="permissions")
public class Permission extends  AuditEntity{

	/**
	 * 
	 */
	private static final long serialVersionUID = 7930766554705439940L;


	@Id
	@Column(name="id")
	private Long id;
	
	
	@Column(name="name")
	private String name;
	
	/**
	 * 访问地址
	 */
	@Column(name="actionurl")
	private String actionUrl;
	
	/**
	 * js文件地址
	 */
	@Column(name="jsurl")
	private String jsUrl;
	
	/**
	 * 等级 1-N
	 */
	@Column(name="level")
	private int level;
	
	/**
	 * 父级编号
	 */
	@Column(name="parentid")
	private Long parentid;
	
	/**
	 * 弹出的控件类
	 */
	@Transient
	private String controlType;
	
	@Transient
	private int leaf;
	
	@Transient
	private boolean checked;
	
	@Transient
	private boolean expanded = true;
	
	@OneToMany(fetch=FetchType.EAGER)
	@JoinColumn(name = "parentid", referencedColumnName="id",insertable=false,updatable=false)
	private List<Permission> children;
	
	public Long getId() {
		return id;
	}

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

	public String getActionUrl() {
		return actionUrl;
	}

	public void setActionUrl(String actionUrl) {
		this.actionUrl = actionUrl;
	}

	public String getJsUrl() {
		return jsUrl;
	}

	public void setJsUrl(String jsUrl) {
		this.jsUrl = jsUrl;
	}

	public int getLevel() {
		return level;
	}

	public void setLevel(int level) {
		this.level = level;
	}

	public Long getParentid() {
		return parentid;
	}

	public void setParentid(Long parentid) {
		this.parentid = parentid;
	}

	@JSON(name="text")
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getControlType() {
		if(this.jsUrl!=null)
			return getControlTypeByDg(this.jsUrl);
		else
			return this.controlType;
	}

	public void setControlType(String controlType) {
		this.controlType = controlType;
	}
	
	public int getLeaf() {
		if(this.level==3){
			return 1;
		}
		return this.leaf;
	}

	public void setLeaf(int leaf) {
		this.leaf = leaf;
	}

	public boolean isChecked() {
		return checked;
	}

	public void setChecked(boolean checked) {
		this.checked = checked;
	}
	
	public List<Permission> getChildren() {
		return children;
	}

	public void setChildren(List<Permission> children) {
		this.children = children;
	}
	
	public boolean isExpanded() {
		return expanded;
	}

	public void setExpanded(boolean expanded) {
		this.expanded = expanded;
	}

	/**
	 * 通过路径获得组件名称
	 * @param path
	 * @return
	 */
	public String getControlTypeByDg(String path){
		if(path.indexOf("/")>=0){
			path = path.replaceFirst(path.substring(path.indexOf("/"),path.indexOf("/")+2), path.substring(path.indexOf("/")+1,path.indexOf("/")+2).toUpperCase());
			
			return getControlTypeByDg(path);
		}else{
			return path;
		}
		
	}

}


package cn.sdh.entity;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OrderBy;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;

import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;

import cn.sdh.common.base.AuditEntity;

/**
 * 角色类
 * @author 孙东辉
 */
@Entity
@Table(name="roles")
public class Role extends  AuditEntity{

	/**
	 * 
	 */
	private static final long serialVersionUID = 5459879676154477558L;

	@Id
	@Column(name="id")
	@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_ROLE")
	@SequenceGenerator(name = "SEQ_ROLE", sequenceName = "SEQ_ROLE", initialValue = 100, allocationSize = 1)
	private Long id;
	
	/**
	 * 角色名称
	 */
	@Column(name="rolename")
	private String roleName;
	
	/**
	 * 拥有的权限集合
	 */
	@ManyToMany(fetch = FetchType.EAGER)
	@Fetch(FetchMode.SUBSELECT)
	@OrderBy("level")
	@JoinTable(name="role_permission",joinColumns={@JoinColumn(name="roleid")},inverseJoinColumns={@JoinColumn(name="perid")})
	private List<Permission> permissionList = new ArrayList<Permission>();
	

	public Long getId() {
		return id;
	}

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

	public String getRoleName() {
		return roleName;
	}

	public void setRoleName(String roleName) {
		this.roleName = roleName;
	}

	public List<Permission> getPermissionList() {
		return permissionList;
	}

	public void setPermissionList(List<Permission> permissionList) {
		this.permissionList = permissionList;
	}

}



Account作为springsecrity的账户类必须实现UserDetails接口,实现的getAuthorities方法是告诉spring当前用户的角色,还有个自定义方法getSignPer用于获取当前用户的权限列表,Permission类有个方法getControlTypeByDg通过配置的jsUrl链接获取Extjs的组件类名,他们的用处后面就能看到,这里补充下我用的是Hibernate的注解方式,严格来讲项目中除了公共配置部分,其他包括Struts Spring等需要xml配置的我全用了注解,如果你对注解不是很了解用xml配置的形式也是可以的

用户通过springsecrity登录成功的时候,会把Account对象保存它的上下文,然后访问这个跳转到主页的action方法,action方法中从springsecrity上下文中获取到Account后通过getSignPer方法获取当前用户的权限(也就是菜单),下面就是用户cccq3y的菜单了


/**
	 * 跳转到主页
	 * 
	 * @throws JSONException
	 */
	public String index() throws JSONException {

		entity = SpringSecurityUtils.getCurrentUser();

		List<Permission> perList = entity.getSignPer();

		HttpServletRequest request = ServletActionContext.getRequest();
		request.setAttribute("perList", perList);
		request.setAttribute("perListJson", JSONUtil.serialize(perList));

		return "index";
	}




当用户点击新增确认按钮时,浏览器会向后台提交一个表单,url为account!save.action,首先会被springsecrity的MyFilterInvocationSecurityMetadataSource拦截到

package cn.sdh.audit;

import java.util.Collection;
import java.util.HashSet;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.stereotype.Service;

import cn.sdh.common.exception.ServiceException;
import cn.sdh.entity.Permission;
import cn.sdh.entity.Role;
import cn.sdh.service.RoleService;
import cn.sdh.utils.MyCacheUtil;

/**
 * 告诉spring当前访问链接 需要什么权限 在这边定义
 * @author 孙东辉
 *
 */
@Service
public class MyFilterInvocationSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {
	
	@Autowired
	private RoleService roleService;
	
	public Collection<ConfigAttribute> getAttributes(Object object)
			throws IllegalArgumentException {
		
		//这个是当前访问的链接
		String requestUrl = ((FilterInvocation) object).getRequestUrl();
		
		//设置哪些页面不需要权限就可访问
		if(requestUrl.indexOf("account!index.action") >= 0 
				|| requestUrl.indexOf("index.jsp") >= 0
				|| requestUrl.indexOf("permission!queryBtnListByControlType.action") >= 0
				|| requestUrl.indexOf("account!searchOnlineList.action")>=0
				|| requestUrl.indexOf("queryDicDataByKey.action")>=0){
			return null;
		}
		
		// 对于带参数的请求,截取?前面的uri
		int urlIndex = requestUrl.indexOf("?");

		if (urlIndex != -1) {
			requestUrl = requestUrl.substring(0, urlIndex);
		}
		
		//如果第一位是/ 去掉
		if(requestUrl.startsWith("/")){
			requestUrl = requestUrl.substring(1);
		}
		
		//从缓存中取当前系统的所有角色
		List<Role> roles = (List<Role>) MyCacheUtil.getRolesList();
		
		
		if(roles == null || roles.size()==0){//如果缓存中没有
			
			try {
				roles = roleService.query();
				
				//把角色放入缓存
				MyCacheUtil.setRolesList(roles);
			} catch (ServiceException e) {
				throw new IllegalArgumentException(e.getMsg());
			}
		}
		
		Collection<ConfigAttribute> c = new HashSet<ConfigAttribute>();
		//遍历所有角色
		List<Permission> permissionList = null;
		if(roles.size()>0){
			for(int i = 0;i<roles.size();i++){
				permissionList = roles.get(i).getPermissionList();
				
				for(int j = 0;j<permissionList.size();j++){
					//如果权限中的actionUrl包含当前访问的链接,当说明现在这个角色是可以访问该链接的
					if(permissionList.get(j)!=null&&permissionList.get(j).getActionUrl()!=null&&permissionList.get(j).getActionUrl().indexOf(requestUrl)>=0){
						ConfigAttribute configAttribute = new SecurityConfig(roles.get(i).getId()+"");
						c.add(configAttribute);
						break;
					}
				}
				
			}
		}else{
			return null;
		}
		
		//最后返回的是一个角色的集合,并且这些角色都是可以访问该链接的
		return c;
	}

	public Collection<ConfigAttribute> getAllConfigAttributes() {
		
		return null;
	}

	public boolean supports(Class<?> clazz) {
		
		return true;
	}
	
}

返回的角色中应该有一个是游客2的id,然后再被MyAccessDecisionManager拦截到
package cn.sdh.audit;

import java.util.Collection;
import java.util.Iterator;

import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;

/**
 * 自定义访问决定器 控制用户能否访问该链接
 * @author sun
 *
 */
public class MyAccessDecisionManager implements AccessDecisionManager {

	
	public void decide(Authentication authentication, Object object,
			Collection<ConfigAttribute> configAttributes)
			throws AccessDeniedException, InsufficientAuthenticationException {
		
		//如果访问的页面没有权限限制 那么不做拦截继续访问 如果未空说明该页面不需要任何角色
		// 注意这里的configAttributes 其实就是MyFilterInvocationSecurityMetadataSource返回的 
		if (configAttributes == null) {
			return;
		}
		
		//如果有权限限制 那么需要迭代权限 验证用户所拥有的权限是否包含 当前页面的访问权限
		Iterator<ConfigAttribute> ite = configAttributes.iterator();
		while (ite.hasNext()) {
			
			//获取访问页面需要的权限
			ConfigAttribute ca = ite.next();
			
			//获取访问页面需要的权限的权限名称
			String needRole = ((SecurityConfig) ca).getAttribute();
			
			//迭代用户所拥有的权限
			for (GrantedAuthority ga : authentication.getAuthorities()) {
				//如果用户的其中一个权限满足 访问链接需要的其中一个权限,那么访问将继续
				if (needRole.equals(ga.getAuthority())) {
					return;
				}
			}
		}
		//否则 访问将被终止
		throw new AccessDeniedException("没有权限访问");
	}

	public boolean supports(ConfigAttribute attribute) {
		// TODO Auto-generated method stub
		return true;
	}

	public boolean supports(Class<?> clazz) {
		// TODO Auto-generated method stub
		return true;
	}

	

}

注释写个很清楚了,把当前用户所拥有的角色和MyFilterInvocationSecurityMetadataSource返回的访问当前链接需要哪些角色,如果包含说明当前用户能访问该链接了,再没抛AccessDeniedException错误的情况下验证都通过

最后再说下前端代码,首先主页的jsp要根据权限加载js文件

<!-- 根据权限加载js文件 -->
	<s:iterator value="#request.perList" var="bean">
		<s:if test="#bean.jsUrl!=null">
			<script type="text/javascript" src="common/jscode/<s:property value="#bean.jsUrl"/>.js"></script>
		</s:if>
	</s:iterator>


然后来感受下extjs4的强大之处了,首先我封装一个公共的权限工具条
/**
 * 权限按钮工具条
 */
Ext.define("app.base.auditbar", {
	extend : "Ext.toolbar.Toolbar",
	alias : 'widget.auditbar',
	initComponent : function() {
		var me = this;
		
		var call = function(){
			var sme = me;
			
			// 根据组件类型 获取它所有的按钮
			Ext.Ajax.request({
				url : 'permission!queryBtnListByControlType.action',
				params : {
					'entity.controlType' : me.compont
				},
				success : new app.ajaxHand({
					success : function(result,scope) {
						var btns = result.searchList;
						
						for ( var i = 0; i < btns.length; i++) {
							if(scope){
								sme = scope;
							}
							sme.insert(i, [ {
								xtype : btns[i].controlType,
								text : btns[i].text
							} ]);
						}
					}
				},sme)

			});
		};
		
		if(me.remote){
			call();
		}
		
		
		if(me.searchItems){
			if(!me.items){
				me.items = [];
			}
			me.items =me.items.concat(['->', {
				xtype : "searchItems",
				items : me.searchItems
			} ]);
		}

		me.callParent(me);
	}
});

然后是grid基类
Ext.define("app.base.grid", {
	extend : "Ext.grid.Panel",
	
	//日期
	dateRender : function(){return Ext.util.Format.dateRenderer(app.constant.date_render);},
	
	//日期加时间
	datetimeRender : function(){return Ext.util.Format.dateRenderer(app.constant.datetime_render);},
	
	//单元格编辑插件
	editingPlugin : function(){ return Ext.create('Ext.grid.plugin.CellEditing',{});},
	
	//行编辑插件
	rowEditingPlugin : function(){return Ext.create('Ext.grid.plugin.RowEditing', {
        clicksToMoveEditor: 1,
        errorSummary : false,
        autoCancel: true
    });},
    
    //行复选框
    selModelPlugin : function(){return Ext.create("Ext.selection.CheckboxModel");},
	
	initComponent : function(){
		var me = this;
		if(me.paging){
			me.bbar = Ext.create('app.base.paging',{
				store:me.store
			});
		}
		me.tbar = Ext.create('app.base.auditbar',{
			compont : me.xtype,
			searchItems : me.searchItems,
			remote:me.auditbarEnable,
			items : me.btns
		});
		
		this.callParent();
	},
	
	//添加行
	addRow : function(){
		this.store.insert(0,new (Ext.ModelManager.getModel(this.model)));
		this.editing.cancelEdit();
		if(this.editing){
			this.editing.startEdit(0,0);
		}
	},
	
	//删除行
	deleteRow : function(){
		
		var recode = this.getSelectionModel().getSelection();
		
		this.store.remove(recode);
	},
	
	//验证选中行
	checkSelectRow : function(count,tip){
		if(!count){
			count = 1;
		}
		tip = tip || "请"+(count!=1?"至少":"")+"选择一行要删除的记录";
		
		var recode = this.getSelectionModel().getSelection();
		
		if(recode.length==0||(count==1&&recode.length>1)){
			app.alert(tip);
			return false;
		}
		
		var usedata = [];
		var ids = "";
		for(var i = 0;i<recode.length;i++){
			usedata.push(recode[i].data);
			ids += recode[i].data.id;
			if(i!=recode.length-1){
				ids += ",";
			}
		}
		usedata.unshift(ids);
		
		return usedata;
	}
	
});

把当前组件的xtype作为参数,到后台获取对应的父级菜单,再根据用户拥有的按钮权限获取这个用户在当前组件的按钮权限,那么问题来了,我是如果通过xtype定位到那条权限数据的呢,真相是我在配置账号管理这个权限的时候配置的jsUrl为user/account/searchGrid然后通过上面Permission类自定义的getControlTypeByDg方法转成xtype,再来看看我的grid子类就清楚了
Ext.define("app.user.account.searchGrid", {
	extend : "app.user.account.grid",
	alias: 'widget.userAccountSearchGrid',

	initComponent : function(){
		var me = this;
		me.editing = me.rowEditingPlugin();
		Ext.apply(this,{
			plugins : [me.editing],
			paging : true,
			selModel : me.selModelPlugin(),
			searchItems :[{
    			fieldLabel : '用户名',
    			xtype : 'textfield',
    			labelAlign : 'right',
    			name : 'entity.username',
    			labelWidth : 45
    		},{
    			fieldLabel : '邮箱',
    			xtype : 'textfield',
    			labelAlign : 'right',
    			name : 'entity.email',
    			labelWidth : 45
    		},{
    			fieldLabel : '上次登录起',
    			xtype : 'datefield',
    			labelAlign : 'right',
    			name : 'entity.lastLoginTime1',
    			labelWidth : 75
    		},{
    			fieldLabel : '上次登录止',
    			xtype : 'datefield',
    			labelAlign : 'right',
    			name : 'entity.lastLoginTime2',
    			labelWidth : 75
    		}]
		});
		
		me.callParent();
	}
});

alias:widget.userAccountSearchGrid,这样就能和后台的权限做对应了,而且在点击菜单树的时候同样用到这个功能,我会根据当前被点击菜单的jsUrl属性转义成xtype,然后很方便的加载对应的组件,就这么简单.最后展示下我的js文件目录




写到这里差不多就结束了,写的有点乱,看不懂的可以加我qq探讨一下;

  • 大小: 71.5 KB
  • 大小: 68.7 KB
  • 大小: 15.5 KB
  • 大小: 20 KB
  • 大小: 6.1 KB
  • 大小: 45.8 KB
  • 大小: 65 KB
  • 大小: 198.7 KB
分享到:
评论

相关推荐

    基于RBAC权限控制模型的后台管理系统

    ① 系统除采用 RBAC 模型进行访问控制以外,还配合 Shiro 框架完成系统的鉴权机制,其中 RBAC 负责左侧菜单级别权限, Shiro 负责按钮级别权限。 ② 系统对于添加修改相关操作采用 Validator 完成表单参数的校验,还...

    java 后台权限管理系统

    是一个简单高效的后台权限管理系统。...安全框架采用时下流行的Apache Shiro,可实现对按钮级别的权限控制;前端页面使用Bootstrap构建,主题风格为时下Google最新设计语言Material Design,并提供多套配色以供选择。

    myshiro:提供一套基于SpringBoot+layui+Shiro+tk_mybatis 的权限管理思路.前后端都加以控制,做到按钮接口级别的权限管理系统 ,在线地址:http

    安全框架采用Shiro,可实现对按钮级别的权限控制,前端页面使用LayUI构建,主题风格小清新简洁, ,使用activiti实现业务流程的管理。 系统模块(已完成) 请假模块 (已完成) 演示环境账号密码: 账号 密码 权限 ...

    PHP和MySQL Web开发第4版pdf以及源码

    《php和mysql web开发(原书第4版)》:开发人员专业技术丛书。 目录 读者反馈 译者序 前言 作者简介 第一篇 使用PHP 第1章 PHP快速入门教程 1.1 开始之前:了解PHP 1.2 创建一个示例应用:Bob汽车零部件商店 ...

    PHP和MySQL WEB开发(第4版)

    9.5.3 权限的类型和级别 9.5.4 REVOKE命令 9.5.5 使用GRANT和REVOKE的例子 9.6 创建一个Web用户 9.7 使用正确的数据库 9.8 创建数据库表 9.8.1 理解其他关键字的意思 9.8.2 理解列的类型 9.8.3 用SHOW和DESCRIBE来...

    PHP和MySQL Web开发第4版

    《php和mysql web开发(原书第4版)》:开发人员专业技术丛书。 目录 读者反馈 译者序 前言 作者简介 第一篇 使用PHP 第1章 PHP快速入门教程 1.1 开始之前:了解PHP 1.2 创建一个示例应用:Bob汽车零部件商店 ...

    简单高效的后台权限管理系统.zip

    安全框架采用Spring Security 5.0.7,可实现对按钮级别的权限控制,并集成了社交账户登录(QQ和微信)以及手机验证码登录;前端页面使用Bootstrap构建,主题风格为时下Google最新设计语言Material Design,并提供多...

    基于Java(SpringBoot) + Vue(Element UI) + UniApp开发的新零售移动电商系统

    JAVA版商城系统是基于Java(SpringBoot) + Vue...10:权限管理,后台多种角色,多重身份权限管理,权限可以控制到按钮级别的操作。 11:Vue表单生成控件,拖拽配置表单,减少前端重复表单工作量,提高前端开发效率。

    Spring Boot 2.0.4 & Shiro1.4.0 权限管理系统

    安全框架采用时下流行的Apache Shiro,可实现对按钮级别的权限控制;前端页面使用Bootstrap构建,主题风格为时下Google最新设计语言Material Design,并提供多套配色以供选择。FEBS意指:Fast,Easy use,Beautiful...

    B2C商城系统java语音开发

    基于Java+Vue+Uni开发,微信公众号、...8.Spring Security 权限管理,后台多种角色,多重身份权限管理,权限可以控制到按钮级别的操作。 9.Vue表单生成控件,拖拽配置表单,减少前端重复表单工作量,提高前端开发效率。

    CRMEB客户管理+电商营销系统Java版

    1:有详细的代码注释,有完整系统手册。...10:权限管理,后台多种角色,多重身份权限管理,权限可以控制到按钮级别的操作。 11:Vue表单生成控件,拖拽配置表单,减少前端重复表单工作量,提高前端开发效率。

    基于Java + Uni-app 开发的新零售社交电商系统 CRMEB Java版

    CRMEB Java版商城系统是一款基于Java + Uni-app ...10:权限管理,后台多种角色,多重身份权限管理,权限可以控制到按钮级别的操作。 11:Vue表单生成控件,拖拽配置表单,减少前端重复表单工作量,提高前端开发效率。

    github-16661027-project-master

    安全框架采用时下流行的Apache Shiro,可实现对按钮级别的权限控制;前端页面使用Bootstrap构建,主题风格为时下Google最新设计语言Material Design,并提供多套配色以供选择。FEBS意指:Fast,Easy use,Beautiful...

    Aurora后台管理系统,完美整合spring boot+shiro+redis

    Aurora是一个简单高效的后台管理系统。...安全框架采用时下流行的Apache Shiro,可实现对按钮级别的权限控制;前端页面使用KidAdmin构建,并提供多套配色以供选择。 项目地址:https://gitee.com/hgpt/Aurora

    CRMEB 【Java版】单商户商城系统v2.0(20211225)(完整包)

    Java 安全框架 Spring Security 权限控制到按钮级别。 任务管理使用quartz 适配集成环境 WEB PC 管理端 表单组件完善 文件上传后回显 多条件显示 初始化引导,让新手都可以了如指掌 WEB PC UI全面更新 多模版选择 小...

    Java新零售社交电商系统源码.rar

    10:权限管理,后台多种角色,多重身份权限管理,权限可以控制到按钮级别的操作。 11:Vue表单生成控件,拖拽配置表单,减少前端重复表单工作量,提高前端开发效率。 运行环境及框架: 1.移动端uniapp开发框架 可...

    CRMEB JAVA版公众号小程序h5 app商城源码

    主要特点 1:有详细的代码注释,有完整系统手册。...10:权限管理,后台多种角色,多重身份权限管理,权限可以控制到按钮级别的操作。 11:Vue表单生成控件,拖拽配置表单,减少前端重复表单工作量,提高前端开发效率。

    CRMEB_开源打通版V4.6微信小程序公众号H5_App多语言分销商城源码.zip

    10:权限管理,后台多种角色,多重身份权限管理,权限可以控制到按钮级别的操作。 11:Vue表单生成控件,拖拽配置表单,减少前端重复表单工作量,提高前端开发效率。 运行环境及框架: 1.移动端uniapp开发框架 可生成...

    CRMEB多商户JAVA版 B2B2C商家入驻平台系统

    (8)Spring Security 权限管理,后台多种角色,多重身份权限管理,权限可以控制到按钮级别的操作; (9)Vue表单生成控件,拖拽配置表单,减少前端重复表单工作量,提高前端开发效率。 功能说明 (1)管理功能齐全...

Global site tag (gtag.js) - Google Analytics