sm整合shiro权限控制

CasUser:

/**
 * Copyright (c) 2020, All Rights Reserved.
 *
*/

package com.micropattern.urp.domain.entity.cas;

import java.util.HashSet;
import java.util.Set;

import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import javax.persistence.Transient;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.micropattern.urp.domain.entity.base.BaseIdAndTime;
import com.micropattern.urp.domain.entity.role.Role;

/**
 * cas集成用户<br/>
 *
 * @author zuo
 * @Date 2020年4月20日 上午11:11:05
 * @since 1.0.0
 *  
 */
@SuppressWarnings("serial")
@Table(name = "t_cas_user")
@Entity
public class CasUser extends BaseIdAndTime{
    
    private String userName;
    private String role;
    @Transient
    private String searchKey;
    private String salt;
    private String password;
    private String remark;
    
    /**
     * 用户角色关系表
     */
    @JsonIgnore
    @ManyToMany
    @JoinTable(name="t_cas_user_role", joinColumns={@JoinColumn(name="user_id",referencedColumnName="id")},
               inverseJoinColumns={@JoinColumn(name="role_id",referencedColumnName="id")})
    private Set<Role> roles = new HashSet<>();

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getRole() {
        return role;
    }

    public void setRole(String role) {
        this.role = role;
    }

    public String getSearchKey() {
        return searchKey;
    }

    public void setSearchKey(String searchKey) {
        this.searchKey = searchKey;
    }

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

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

    public String getSalt() {
        return salt;
    }

    public void setSalt(String salt) {
        this.salt = salt;
    }

    public String getPassword() {
        return password;
    }

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

    public String getRemark() {
        return remark;
    }

    public void setRemark(String remark) {
        this.remark = remark;
    }
    
}
View Code

Role:

/**
 * Copyright (c) 2020, All Rights Reserved.
 *
*/

package com.micropattern.urp.domain.entity.role;

import java.util.HashSet;
import java.util.Set;

import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.micropattern.urp.domain.entity.base.BaseIdAndTime;
import com.micropattern.urp.domain.entity.cas.CasUser;
import com.micropattern.urp.domain.entity.permission.Permission;

/**
 * 此处应有类说明<br/>
 *
 * @author why
 * @Date 2020年4月13日 下午3:36:58
 * @since 1.0.0
 *  
 */
@SuppressWarnings("serial")
@Table(name = "t_cas_role")
@Entity
public class Role extends BaseIdAndTime{
    /**
     * 角色名
     */
    private String name;
    
    private Boolean delFlag;
    
    private String remark;
    
    /**
     * 角色,用户,多对多
     */
    @JsonIgnore
    @ManyToMany(mappedBy="roles")
    private Set<CasUser> users=new HashSet<>();
    
    @JsonIgnore
    @ManyToMany
    @JoinTable(name="t_cas_role_permission", joinColumns={@JoinColumn(name="role_id",referencedColumnName="id")},
               inverseJoinColumns={@JoinColumn(name="permission_id",referencedColumnName="id")})
    private Set<Permission> permissions = new HashSet<>();

    public Set<Permission> getPermissions() {
        return permissions;
    }

    public void setPermissions(Set<Permission> permissions) {
        this.permissions = permissions;
    }

    public Boolean getDelFlag() {
        return delFlag;
    }

    public void setDelFlag(Boolean delFlag) {
        this.delFlag = delFlag;
    }

    public String getName() {
        return name;
    }

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

    public Set<CasUser> getUsers() {
        return users;
    }

    public void setUsers(Set<CasUser> users) {
        this.users = users;
    }

    public String getRemark() {
        return remark;
    }

    public void setRemark(String remark) {
        this.remark = remark;
    }
    
}
View Code

Permission:

/**
 * Copyright (c) 2020, All Rights Reserved.
 *
*/

package com.micropattern.urp.domain.entity.permission;

import javax.persistence.Entity;
import javax.persistence.Table;
import javax.persistence.Transient;

import com.micropattern.urp.domain.entity.base.BaseIdAndTime;

/**
 * 此处应有类说明<br/>
 *
 * @author why
 * @Date 2020年4月13日 下午3:50:53
 * @since 1.0.0
 *  
 */
@SuppressWarnings("serial")
@Table(name = "t_cas_permission")
@Entity
public class Permission extends BaseIdAndTime{
    
    /**
     * 权限名称
     */
    private String name;
    /**
     * 权限类型
     */
    private Integer type;
    /**
     * 资源路径
     */
    private String url;
    
    private Boolean delFlag;
    
    /**
     * 是否勾选
     * true : 勾选
     * false : 未勾选
     */
    @Transient
    private Boolean checked;
    
    /**
     * 排序
     */
    private Integer sort;
    
    /**
     * 菜单等级
     * 1:父节点
     * 2:子节点
     */
    private Integer level;
    
    /**
     * 父id
     */
    private String parentId;
    
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getType() {
        return type;
    }
    public void setType(Integer type) {
        this.type = type;
    }
    public String getUrl() {
        return url;
    }
    public void setUrl(String url) {
        this.url = url;
    }
    public Boolean getDelFlag() {
        return delFlag;
    }
    public void setDelFlag(Boolean delFlag) {
        this.delFlag = delFlag;
    }
    public Boolean getChecked() {
        return checked;
    }
    public void setChecked(Boolean checked) {
        this.checked = checked;
    }
    public Integer getSort() {
        return sort;
    }
    public void setSort(Integer sort) {
        this.sort = sort;
    }
    public Integer getLevel() {
        return level;
    }
    public void setLevel(Integer level) {
        this.level = level;
    }
    public String getParentId() {
        return parentId;
    }
    public void setParentId(String parentId) {
        this.parentId = parentId;
    }
   
}
View Code

建表sql:

CREATE TABLE `t_cas_user` (
  `id` varchar(255) NOT NULL COMMENT '用户id',
  `password` varchar(255) DEFAULT NULL COMMENT '密码',
  `user_name` varchar(64) DEFAULT NULL COMMENT '用户名',
  `role` varchar(64) DEFAULT NULL COMMENT '角色',
  `salt` varchar(64) DEFAULT NULL COMMENT '密码盐',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  `create_user` varchar(64) DEFAULT NULL COMMENT '创建用户',
  `update_time` datetime DEFAULT NULL COMMENT '更新时间',
  `update_user` varchar(64) DEFAULT NULL COMMENT '更新用户',
  `version` int(11) DEFAULT '0',
  `remark` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `t_cas_user_role` (
  `user_id` varchar(255) NOT NULL,
  `role_id` varchar(255) NOT NULL,
  PRIMARY KEY (`user_id`,`role_id`),
  KEY `FK_h6p8coxk4oxl6txq1hd7jim82` (`role_id`),
  CONSTRAINT `FK_h6p8coxk4oxl6txq1hd7jim82` FOREIGN KEY (`role_id`) REFERENCES `t_cas_role` (`id`),
  CONSTRAINT `FK_oajhcq0g0st27cocwugnq47mf` FOREIGN KEY (`user_id`) REFERENCES `t_cas_user` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


CREATE TABLE `t_cas_role` (
  `id` varchar(255) NOT NULL,
  `name` varchar(64) DEFAULT NULL COMMENT '权限名称',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  `create_user` varchar(255) DEFAULT NULL COMMENT '创建用户',
  `update_time` datetime DEFAULT NULL COMMENT '更新时间',
  `update_user` varchar(255) DEFAULT NULL COMMENT '更新用户',
  `version` int(11) DEFAULT '0' COMMENT '版本号',
  `del_flag` bit(1) DEFAULT NULL COMMENT '是否删除,0:未删除',
  `remark` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='角色表';


CREATE TABLE `t_cas_role_permission` (
  `role_id` varchar(255) NOT NULL,
  `permission_id` varchar(255) NOT NULL,
  PRIMARY KEY (`role_id`,`permission_id`),
  KEY `FK_ssde3tsrhwnl5s15n0cys16p0` (`permission_id`),
  CONSTRAINT `FK_13au68ku0hwd8b01mtpdp49mo` FOREIGN KEY (`role_id`) REFERENCES `t_cas_role` (`id`),
  CONSTRAINT `FK_ssde3tsrhwnl5s15n0cys16p0` FOREIGN KEY (`permission_id`) REFERENCES `t_cas_permission` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


CREATE TABLE `t_cas_permission` (
  `id` varchar(255) NOT NULL COMMENT '主键',
  `name` varchar(100) DEFAULT NULL COMMENT '权限名称',
  `type` int(11) DEFAULT NULL COMMENT '权限类型,1:菜单 2:按钮 3:API',
  `url` varchar(200) DEFAULT NULL COMMENT '资源路径',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  `create_user` varchar(255) DEFAULT NULL COMMENT '创建用户',
  `update_time` datetime DEFAULT NULL COMMENT '更新时间',
  `update_user` varchar(255) DEFAULT NULL COMMENT '更新用户',
  `version` int(11) DEFAULT '0' COMMENT '版本号',
  `del_flag` bit(1) DEFAULT NULL COMMENT '是否删除,0:未删除',
  `sort` int(11) DEFAULT '0' COMMENT '排序',
  `parent_id` varchar(64) DEFAULT NULL COMMENT '父id',
  `level` int(11) DEFAULT NULL COMMENT '权限等级,1:父节点,2:子节点',
  PRIMARY KEY (`id`),
  UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='资源表';
View Code

spring-shiro.xml:

<?xml version="1.0" encoding="UTF-8"?>  
<beans xmlns="http://www.springframework.org/schema/beans"  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    xsi:schemaLocation="http://www.springframework.org/schema/beans   
                        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd" 
    default-lazy-init="true">
  
    <description>Shiro Configuration</description>  
  
    <!-- 安全管理器 -->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="realm" ref="userRealm" />
        <property name="cacheManager" ref="cacheManager" />
        <!--设置会话管理器-->
        <!-- <property name="sessionManager" ref="sessionManager"></property> -->
    </bean>  
  
    <!-- 項目自定义的Realm -->  
    <bean id="userRealm" class="com.micropattern.urp.common.shiro.UserRealm">  
        <property name="cacheManager" ref="cacheManager" />
        <!-- <property name="credentialsMatcher" ref="credentialsMatcher"></property> -->
        <property name="credentialsMatcher" ref="customCredentialsMatcher"></property>
    </bean>  
  
    <!-- Shiro Filter -->  
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">  
        <property name="securityManager" ref="securityManager" />  
        <!-- 用户登录地址 -->
        <property name="loginUrl" value="/login"/>  
        <!-- 登录成功 -->
        <property name="successUrl" value="/login"/>  
        <!-- 未授权的失败页 -->
        <property name="unauthorizedUrl" value="/error"/>
        <property name="filterChainDefinitions">
            <value>  
                 <!-- 设置访问用户list页面需要授权操作 -->
                /** = anon
                /manage = anon
                
            </value>  
        </property>  
    </bean>  
    
    <!--配置会话管理器-->
    <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
        <!--设置session的超时时间20min-->
        <property name="globalSessionTimeout" value="1200000"></property>
        <!--删除失效session-->
        <property name="deleteInvalidSessions" value="true"></property>
    </bean>
  
   <!-- 给予shior的内存缓存系统 -->
    <bean id="cacheManager" class="org.apache.shiro.cache.MemoryConstrainedCacheManager"/>  
  
    <!-- 保证实现了Shiro内部lifecycle函数的bean执行 -->  
    <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />  
  
    <!-- <bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
        <property name="hashAlgorithmName" value="SHA-512"></property>
        <property name="hashIterations" value="2"></property>
    </bean> -->
    
    <bean id="customCredentialsMatcher" class="com.micropattern.urp.common.shiro.CustomCredentialsMatcher"/>

    
</beans>
View Code

UserRealm:

/**
 * Copyright (c) 2020, All Rights Reserved.
 *
 */

package com.micropattern.urp.common.shiro;

import java.util.HashSet;
import java.util.Set;

import org.apache.shiro.SecurityUtils;
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.CredentialsMatcher;
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.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import com.micropattern.urp.common.constant.ErrorCode.SystemUserError;
import com.micropattern.urp.common.enums.SystemUserStatus;
import com.micropattern.urp.common.exception.BusinessException;
import com.micropattern.urp.domain.entity.permission.Permission;
import com.micropattern.urp.domain.entity.role.Role;
import com.micropattern.urp.domain.entity.system.User;
import com.micropattern.urp.domain.service.system.UserService;

/**
 * shiro管理<br/>
 *
 * @author zuo
 * @Date 2020年4月13日 下午2:10:29
 * @since 1.0.0
 * 
 */
public class UserRealm extends AuthorizingRealm {

    @Autowired
    private UserService userService;

    //授权认证
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        System.out.println("=============执行授权逻辑================");
        Set<String> set = new HashSet<>();// 权限集合
        // 给资源进行授权
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        User tokenUser = (User) principals.getPrimaryPrincipal();
        User user = userService.findByUserName(tokenUser.getUserName());
        Set<Role> roles = user.getRoles();
        for (Role role : roles) {
            Set<Permission> permissions = role.getPermissions();
            for (Permission permission : permissions) {
                set.add(permission.getUrl());
            }
        }
        simpleAuthorizationInfo.addStringPermissions(set);
        return simpleAuthorizationInfo;
    }

    //登录认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("=============执行认证逻辑================");
        UsernamePasswordToken tokens = (UsernamePasswordToken) token;
        User user = userService.findByUserName(tokens.getUsername());
        if (user == null) {
            throw new BusinessException(SystemUserError.USER_NAME_NOTEXISTS);
        }
        if (user.getDelFlag()) {
            throw new BusinessException(SystemUserError.USER_NAME_NOTEXISTS);
        } else if (SystemUserStatus.ENABLE != user.getStatus()) {
            throw new BusinessException(SystemUserError.LOGIN_FORBID);
        }
        SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(user, user.getPassword(),
                ByteSource.Util.bytes(user.getSalt()), getName());
        return simpleAuthenticationInfo;
    }

    //自定义密码校验
    @Override
    public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) {
        super.setCredentialsMatcher(new CustomCredentialsMatcher());
    }

    //清空权限缓存 
    public void clearCachedAuthorization(){
        clearCachedAuthorizationInfo(SecurityUtils.getSubject().getPrincipals());
    }
    
}
View Code

shiro清空缓存:

/**
 * Copyright (c) 2020, All Rights Reserved.
 *
*/

package com.micropattern.urp.common.shiro;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.mgt.RealmSecurityManager;

/**
 * shiro清除缓存<br/>
 *
 * @author zuo
 * @Date 2020年4月17日 上午9:25:50
 * @since 1.0.0
 *  
 */
public class ShiroUtils {
    
    public static void clearShiroCache(){
        RealmSecurityManager rsm = (RealmSecurityManager)SecurityUtils.getSecurityManager();
        UserRealm realm = (UserRealm)rsm.getRealms().iterator().next();
        realm.clearCachedAuthorization();
    }
    
}
View Code

自定义加密类:

/**
 * Copyright (c) 2018, All Rights Reserved.
 * 
 */

package com.micropattern.urp.common.utils;

import java.security.MessageDigest;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.lang3.RandomStringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 签名加密工具类<br/>
 * Date: 2018年1月29日 下午2:15:59 <br/>
 * 
 * @author xin.zhou
 * @version
 * @since JDK 1.7
 * @see
 */
public class SignUtils {
    private static final Logger LOG = LoggerFactory.getLogger(SignUtils.class);
    private static final String DEFAULT_CHARSET = "UTF-8";
    private static final char[] DIGITS;

    public static String hmacSha256(String key, String data) {
        try {
            Mac mac = Mac.getInstance("HmacSHA256");
            SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(), mac.getAlgorithm());
            mac.init(signingKey);
            return encodeHex(mac.doFinal(data.getBytes()));
        } catch (Exception e) {
            LOG.error("execute hmacSHA256 error", e);
        }

        return null;
    }

    private static String encrypt(String algorithm, String data, String charset) {
        try {
            byte[] msg = data.getBytes(charset);
            MessageDigest md = MessageDigest.getInstance(algorithm);
            return encodeHex(md.digest(msg));
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
        }
        return null;
    }

    public static String md5(String data, String charset) {
        return encrypt("MD5", data, charset);
    }

    public static String sha1(String data, String charset) {
        return encrypt("SHA1", data, charset);
    }

    public static String sha1(String data) {
        return sha1(data, DEFAULT_CHARSET);
    }

    public static String sha256(String data, String charset) {
        return encrypt("SHA-256", data, charset);
    }

    public static String sha256(String data) {
        return sha256(data, DEFAULT_CHARSET);
    }

    public static String sha512(String data, String charset) {
        return encrypt("SHA-512", data, charset);
    }

    public static String sha512(String data) {
        return sha512(data, DEFAULT_CHARSET);
    }

    private static String encodeHex(byte[] data) {
        int l = data.length;
        char[] out = new char[l << 1];
        int i = 0;

        for (int j = 0; i < l; ++i) {
            out[j++] = DIGITS[(240 & data[i]) >>> 4];
            out[j++] = DIGITS[15 & data[i]];
        }

        return new String(out);
    }

    static {
        DIGITS = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
    }
    
    public static void main(String[] args) {
        //UPJW1u
        //1d0c7526881640dfb2a7018c9e2328a3b520b6236bf53378b42059578cc603ffa81c159384119c5bcf280d16503abe32d747104e7c409d53c90ced1e7136fe10
        String salt=RandomStringUtils.randomAlphanumeric(6);
        System.out.println(salt+" "+sha512("123456"+salt));
    }
}
View Code

shiro加密校验:

/**
 * Copyright (c) 2020, All Rights Reserved.
 *
*/

package com.micropattern.urp.common.shiro;

import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.SimpleCredentialsMatcher;
import org.apache.shiro.subject.PrincipalCollection;
import com.micropattern.urp.common.utils.SignUtils;
import com.micropattern.urp.domain.entity.system.User;

/**
 * 自定义shiro密码校验<br/>
 *
 * @author zuo
 * @Date 2020年4月14日 下午5:30:44
 * @since 1.0.0
 *  
 */
public class CustomCredentialsMatcher extends SimpleCredentialsMatcher {
    
    @Override
    public boolean doCredentialsMatch(AuthenticationToken authcToken, AuthenticationInfo info) {
        UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
        PrincipalCollection principals = info.getPrincipals();
        User user = (User) principals.getPrimaryPrincipal();
        String salt = user.getSalt();
        String password = String.valueOf(token.getPassword());
        Object tokenCredentials = encrypt(password, salt);
        Object accountCredentials = getCredentials(info);
        //将密码加密与系统加密后的密码校验,内容一致就返回true,不一致就返回false
        return equals(tokenCredentials, accountCredentials);
    }

    //密码加密方法
    private String encrypt(String password, String salt) {
        return SignUtils.sha512(password + salt);
    }

    
}
View Code

页面按钮控制:

<@shiro.hasPermission name="sysuser:add">
<button class="btn btn-primary btn-xs" id="addBtn"><i class="ace-icon glyphicon glyphicon-plus"></i>新增</button>
</@shiro.hasPermission>

posted @ 2020-04-26 10:54  所向披靡zz  阅读(270)  评论(0编辑  收藏  举报