Package com.ketayao.ketacustom.shiro

Source Code of com.ketayao.ketacustom.shiro.ShiroDbRealm$HashPassword

/**
* <pre>
* Copyright:    Copyright(C) 2011-2012, ketayao.com
* Filename:    com.ketayao.ketacustom.shiro.ShiroDbRealm.java
* Class:      ShiroDbRealm
* Date:      2012-8-2
* Author:      <a href="mailto:ketayao@gmail.com">ketayao</a>
* Version          1.1.0
* Description:   
*
* </pre>
**/

package com.ketayao.ketacustom.shiro;

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 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.DisabledAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ketayao.ketacustom.entity.main.DataControl;
import com.ketayao.ketacustom.entity.main.OrganizationRole;
import com.ketayao.ketacustom.entity.main.Permission;
import com.ketayao.ketacustom.entity.main.Role;
import com.ketayao.ketacustom.entity.main.RolePermission;
import com.ketayao.ketacustom.entity.main.RolePermissionDataControl;
import com.ketayao.ketacustom.entity.main.User;
import com.ketayao.ketacustom.entity.main.UserRole;
import com.ketayao.ketacustom.service.OrganizationRoleService;
import com.ketayao.ketacustom.service.RoleService;
import com.ketayao.ketacustom.service.UserRoleService;
import com.ketayao.ketacustom.service.UserService;
import com.ketayao.ketacustom.util.dwz.Page;
import com.ketayao.utils.Digests;
import com.ketayao.utils.Encodes;

/**
*
* @author <a href="mailto:ketayao@gmail.com">ketayao</a> Version 1.1.0
* @since 2012-8-2 下午3:09:50
*/

public class ShiroDbRealm extends AuthorizingRealm {
  private static final Logger log = LoggerFactory.getLogger(ShiroDbRealm.class);
 
  private static final int INTERATIONS = 1024;
  private static final int SALT_SIZE = 8;
  private static final String ALGORITHM = "SHA-1";

  // 是否启用超级管理员
  protected boolean activeRoot = false;
 
  // 是否使用验证码
  protected boolean useCaptcha = false;
 
  protected UserService userService;
 
  protected RoleService roleService;
 
  protected UserRoleService userRoleService;
 
  protected OrganizationRoleService organizationRoleService;
 
  /**
   * 给ShiroDbRealm提供编码信息,用于密码密码比对
   * 描述
   */ 
  public ShiroDbRealm() {
    super();
    HashedCredentialsMatcher matcher = new HashedCredentialsMatcher(ALGORITHM);
    matcher.setHashIterations(INTERATIONS);

    setCredentialsMatcher(matcher);
  }
 
  /**
   * 认证回调函数, 登录时调用.
   */
  // TODO 对认证进行缓存处理
  @Override
  protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
    if (useCaptcha) {
      CaptchaUsernamePasswordToken token = (CaptchaUsernamePasswordToken) authcToken;
      String parm = token.getCaptcha();
     
      if (!PatchcaServlet.validate(SecurityUtils
          .getSubject().getSession().getId().toString(), parm.toLowerCase())) {//忽略大小写。
        throw new IncorrectCaptchaException("验证码错误!");
      }
    }
   
    UsernamePasswordToken token = (UsernamePasswordToken)authcToken;
    User user = userService.getByUsername(token.getUsername());
    if (user != null) {
      if (user.getStatus().equals(User.STATUS_DISABLED)) {
        throw new DisabledAccountException();
      }
     
      byte[] salt = Encodes.decodeHex(user.getSalt());
     
      ShiroUser shiroUser = new ShiroUser(user.getId(), user.getUsername());
     
      // 这里可以缓存认证
      return new SimpleAuthenticationInfo(shiroUser, user.getPassword(),
          ByteSource.Util.bytes(salt), getName());
    } else {
      return null;
    }
   
  }

  /**
   * 授权查询回调函数, 进行鉴权但缓存中无用户的授权信息时调用.
   */
  @Override
  protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
    Collection<?> collection = principals.fromRealm(getName());
    if (collection == null || collection.isEmpty()) {
      return null;
    }
   
    ShiroUser shiroUser = (ShiroUser) collection.iterator().next();
    // 设置、更新User
    shiroUser.setUser(userService.get(shiroUser.getId()));
    return newAuthorizationInfo(shiroUser);
  }
 
  private SimpleAuthorizationInfo newAuthorizationInfo(ShiroUser shiroUser) {
    Collection<String> hasPermissions = null;
    Collection<String> hasRoles = null;
   
    // 是否启用超级管理员 && id==1为超级管理员,构造所有权限
    if (activeRoot && shiroUser.getId() == 1) {
      hasRoles = new HashSet<String>();
      Page page = new Page();
      page.setNumPerPage(Integer.MAX_VALUE);
      List<Role> roles = roleService.findAll(page);
     
      for (Role role : roles) {
        hasRoles.add(role.getName());
      }
     
      hasPermissions = new HashSet<String>();
      hasPermissions.add("*");
     
      if (log.isInfoEnabled()) {
        log.info("使用了" + shiroUser.getLoginName() + "的超级管理员权限:" + "。At " + new Date());
        log.info(shiroUser.getLoginName() + "拥有的角色:" + hasRoles);
        log.info(shiroUser.getLoginName() + "拥有的权限:" + hasPermissions);
      }
    } else {
      List<UserRole> userRoles = userRoleService.findByUserId(shiroUser.getId());
      List<OrganizationRole> organizationRoles = organizationRoleService
          .findByOrganizationId(shiroUser.getUser().getOrganization().getId());
     
      Collection<Role> roles = getUserRoles(userRoles, organizationRoles);
      hasRoles = makeRoles(roles, shiroUser);
      hasPermissions = makePermissions(roles, shiroUser);
    }
   
    SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
    info.addRoles(hasRoles);
    info.addStringPermissions(hasPermissions);
   
    return info;
  }
 
  private Collection<Role> getUserRoles(List<UserRole> userRoles, List<OrganizationRole> organizationRoles) {
    Set<Role> roles = new HashSet<Role>();
    for (UserRole userRole : userRoles) {
      roles.add(userRole.getRole());
    }
   
    for (OrganizationRole organizationRole : organizationRoles) {
      roles.add(organizationRole.getRole());
    }
   
    return roles;
  }
 
  /**
   * 组装角色权限
   * @param roles
   * @param shiroUser
   * @return
   */
  private Collection<String> makeRoles(Collection<Role> roles, ShiroUser shiroUser) {
    Collection<String> hasRoles = new HashSet<String>();
    for (Role role : roles) {
      hasRoles.add(role.getName());
    }

    if (log.isInfoEnabled()) {
      log.info(shiroUser.getLoginName() + "拥有的角色:" + hasRoles);
    }
    return hasRoles;
  }
 
  /**
   * 组装资源操作权限
   * @param roles
   * @param shiroUser
   * @return
   */
  private Collection<String> makePermissions(Collection<Role> roles, ShiroUser shiroUser) {
    // 清空shiroUser中map
    shiroUser.getHasDataControls().clear();
    shiroUser.getHasModules().clear();
   
    Collection<String> stringPermissions = new ArrayList<String>();
    for (Role role : roles) {
      List<RolePermission> rolePermissions = role.getRolePermissions();
      for (RolePermission rolePermission : rolePermissions) {
        Permission permission = rolePermission.getPermission();
       
        String resource = permission.getModule().getSn();
        String operate = permission.getSn();
   
        StringBuilder builder = new StringBuilder();
        builder.append(resource + ":" + operate);
       
        shiroUser.getHasModules().put(resource, permission.getModule());
       
        StringBuilder dcBuilder = new StringBuilder();
        for (RolePermissionDataControl rpdc : rolePermission.getRolePermissionDataControls()) {
          DataControl dataControl = rpdc.getDataControl();
          dcBuilder.append(dataControl.getName() + ",");
         
          shiroUser.getHasDataControls().put(dataControl.getName(), dataControl);
        }
       
        if (dcBuilder.length() > 0) {
          builder.append(":" + dcBuilder.substring(0, dcBuilder.length() - 1));
        }
       
        stringPermissions.add(builder.toString());
      }
    }

    if (log.isInfoEnabled()) {
      log.info(shiroUser.getLoginName() + "拥有的权限:" + stringPermissions);
    }
    return stringPermissions;
  }
 
  public static class HashPassword {
    public String salt;
    public String password;
  }
 
  public static HashPassword encryptPassword(String plainPassword) {
    HashPassword result = new HashPassword();
    byte[] salt = Digests.generateSalt(SALT_SIZE);
    result.salt = Encodes.encodeHex(salt);

    byte[] hashPassword = Digests.sha1(plainPassword.getBytes(), salt, INTERATIONS);
    result.password = Encodes.encodeHex(hashPassword);
    return result;
  }
 
  /**
   *
   * 验证密码
   * @param plainPassword 明文密码
   * @param password 密文密码
   * @param salt 盐值
   * @return
   */
  public static boolean validatePassword(String plainPassword, String password, String salt) {
    byte[] hashPassword = Digests.sha1(plainPassword.getBytes(), Encodes.decodeHex(salt), INTERATIONS);
    String oldPassword = Encodes.encodeHex(hashPassword);
    return password.equals(oldPassword);
  }
 
  /*
   * 覆盖父类方法,设置AuthorizationCacheKey为ShiroUser的loginName,这样才能顺利删除shiro中的缓存。
   * 因为shiro默认的AuthorizationCacheKey为PrincipalCollection的对象。
   * @see org.apache.shiro.realm.AuthorizingRealm#getAuthorizationCacheKey(org.apache.shiro.subject.PrincipalCollection)
   */
  @Override
  protected Object getAuthorizationCacheKey(PrincipalCollection principals) {
    ShiroUser shiroUser = (ShiroUser)principals.getPrimaryPrincipal();
    return shiroUser.getLoginName();
  }

  /**
   * 更新用户授权信息缓存.
   */
  public void clearCachedAuthorizationInfo(String loginName) {
    ShiroUser shiroUser = new ShiroUser(loginName);
   
    SimplePrincipalCollection principals = new SimplePrincipalCollection(shiroUser, getName());
    clearCachedAuthorizationInfo(principals);
  }

  /**
   * 清除所有用户授权信息缓存.
   */
  public void clearAllCachedAuthorizationInfo() {
    Cache<Object, AuthorizationInfo> cache = getAuthorizationCache();
    if (cache != null) {
      for (Object key : cache.keys()) {
        cache.remove(key);
      }
    }
  }
 
  /** 
   * 设置 isActiveRoot 的值 
   * @param isActiveRoot
   */
  public void setActiveRoot(boolean activeRoot) {
    this.activeRoot = activeRoot;
  }

  /** 
   * 设置 useCaptcha 的值 
   * @param useCaptcha
   */
  public void setUseCaptcha(boolean useCaptcha) {
    this.useCaptcha = useCaptcha;
  }

  public void setUserService(UserService userService) {
    this.userService = userService;
  }
 
  /** 
   * 设置 userRoleService 的值 
   * @param userRoleService
   */
  public void setUserRoleService(UserRoleService userRoleService) {
    this.userRoleService = userRoleService;
  }

  /** 
   * 设置 organizationRoleService 的值 
   * @param organizationRoleService
   */
  public void setOrganizationRoleService(
      OrganizationRoleService organizationRoleService) {
    this.organizationRoleService = organizationRoleService;
  }

  /**
   * @param roleService the roleService to set
   */
  public void setRoleService(RoleService roleService) {
    this.roleService = roleService;
  }
}
TOP

Related Classes of com.ketayao.ketacustom.shiro.ShiroDbRealm$HashPassword

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.