jar:
<shiro.version>1.2.3</shiro.version>
<!-- shiro -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>${shiro.version}</version>
</dependency>
自定义自定义 Realm:
import com.xmdishi.fmp.model.po.business.BusinessMenuPo;
import com.xmdishi.fmp.model.po.business.BusinessUserPo;
import com.xmdishi.fmp.model.qo.business.BusinessUserQo;
import com.xmdishi.fmp.service.business.BusinessMenuService;
import com.xmdishi.fmp.service.business.BusinessUserService;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* 自定义 Realm
* @author cjianquan
* @date 2020/4/6
* @param
* @return
*/
@Component
public class CustomRealm extends AuthorizingRealm {
@Autowired
private BusinessUserService businessUserService;
@Autowired
private BusinessMenuService businessMenuService;
private static Logger logger=LoggerFactory.getLogger(CustomRealm.class);
public CustomRealm() {logger.info("CustomRealm====================");
}
@Override
public String getName() {return "CustomRealm";}
@Bean(name = "credentialsMatcher")
public HashedCredentialsMatcher credentialsMatcher(){HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
credentialsMatcher.setHashAlgorithmName("md5");
credentialsMatcher.setHashIterations(1);
return credentialsMatcher;
}
@Override
public void setCredentialsMatcher(@Qualifier("credentialsMatcher")CredentialsMatcher credentialsMatcher){super.setCredentialsMatcher(credentialsMatcher);
}
/**
* realm 受权办法 从输出参数 principalCollection 失去身份信息 依据身份信息到数据库查找权限信息 将权限信息增加给受权信息对象
* 返回 受权信息对象 (判断用户拜访 url 是否在权限信息中没有体现)
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {BusinessUserPo user = (BusinessUserPo) principalCollection.getPrimaryPrincipal();
String roleIds = user.getRoleIds();
List<String> btnList = null;
try{btnList = businessMenuService.queryBtnsByRoles(roleIds);
}catch (Exception e){e.printStackTrace();
}
// 用户权限列表
Set<String> permsSet = new HashSet<String>();
if(btnList!=null && btnList.size()>0){permsSet.addAll(btnList);
}
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.setStringPermissions(permsSet);
return info;
}
/**
* 表单认证过滤器认证时会调用自定义 Realm 的认证办法进行认证,胜利回到 index.do,再跳转到 index.jsp 页面
*
* 前提:表单认证过滤器收集和组织用户名和明码信息封装为 token 对象传递给此办法
*
* token: 封装了身份信息和凭证信息 2 步骤:比对身份 信息;比对凭证
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {String username = (String) token.getPrincipal();
String password = new String((char[]) token.getCredentials());
// 查问用户信息
BusinessUserQo userQo = new BusinessUserQo();
userQo.setUserName(username);
List<BusinessUserPo> userList = null;
BusinessUserPo businessUserPo = null;
try{userList = this.businessUserService.query(userQo);
if(userList!=null && userList.size()>0){businessUserPo = userList.get(0);
}
}catch (Exception e){e.printStackTrace();
}
// 账号不存在
if (businessUserPo == null) {throw new UnknownAccountException("账号不存在!");
}
// 明码谬误
if (!password.equals(businessUserPo.getPassword())) {throw new IncorrectCredentialsException("账号或明码不正确!");
}
// 账号未调配角色
if (businessUserPo.getRoleIds() == null ) {throw new UnknownAccountException("账号未调配角色!");
}
//cjianquan 2020/2/8 登录胜利,查问菜单
try{List<BusinessMenuPo> menuList = this.businessMenuService.queryByRoles(businessUserPo.getRoleIds());
businessUserPo.setMenuList(menuList);
}catch (Exception e){e.printStackTrace();
}
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(businessUserPo, password, getName());
return info;
}
}
web.xml 增加 :
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<param-name>targetFilterLifecycle</param-name>
<param-value>true</param-value>
</init-param>
<!-- targetBeanName??spring?shiro??????bean?id??? -->
<init-param>
<param-name>targetBeanName</param-name>
<param-value>shiroFilter</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<!-- ????url???shiro?????? -->
<url-pattern>/*</url-pattern>
</filter-mapping>
SpringShiroConfig:
import com.xmdishi.fmp.business.shiro.CustomRealm;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.config.MethodInvokingFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import java.util.LinkedHashMap;
import java.util.Map;
@Configuration
public class SpringShiroConfig {
@Autowired
private CustomRealm realm;
public SpringShiroConfig() {System.out.println("SpringShiroConfig init ......");
}
@Bean(name = "lifecycleBeanPostProcessor")
public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {return new LifecycleBeanPostProcessor();
}
@Bean
@DependsOn("lifecycleBeanPostProcessor")
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
creator.setProxyTargetClass(true);
creator.setUsePrefix(true);
return creator;
}
@Bean
public MethodInvokingFactoryBean getMethodInvokingFactoryBean(@Qualifier("securityManager")SecurityManager securityManager) {MethodInvokingFactoryBean methodInvokingFactoryBean=new MethodInvokingFactoryBean();
methodInvokingFactoryBean.setStaticMethod("org.apache.shiro.SecurityUtils.setSecurityManager");
methodInvokingFactoryBean.setArguments(new Object[]{securityManager});
return methodInvokingFactoryBean;
}
//get
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager")SecurityManager securityManager) {AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
//get
@Bean(name = "shiroFilter")
public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("securityManager")SecurityManager securityManager){ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setLoginUrl("/index.jsp");
shiroFilterFactoryBean.setSuccessUrl("/index.jsp");
shiroFilterFactoryBean.setUnauthorizedUrl("/index.jsp");
shiroFilterFactoryBean.setSecurityManager(securityManager);
loadShiroFilterChain(shiroFilterFactoryBean);
return shiroFilterFactoryBean;
}
//get
@Bean(name = "sessionManager")
public DefaultWebSessionManager sessionManager(){DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
sessionManager.setGlobalSessionTimeout(86400000);
sessionManager.setDeleteInvalidSessions(true);
return sessionManager;
}
//get
@Bean(name = "shiroCacheManager")
public EhCacheManager shiroCacheManager(){EhCacheManager shiroCacheManager = new EhCacheManager();
shiroCacheManager.setCacheManagerConfigFile("classpath:shiro-ehcache.xml");
return shiroCacheManager;
}
//get
@Bean(name = "securityManager")
public DefaultWebSecurityManager securityManager(@Qualifier("shiroCacheManager") EhCacheManager shiroCacheManager,
@Qualifier("sessionManager") DefaultWebSessionManager sessionManager) {DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(realm);
securityManager.setCacheManager(shiroCacheManager);
securityManager.setSessionManager(sessionManager);
return securityManager;
}
//get
private void loadShiroFilterChain(ShiroFilterFactoryBean shiroFilterFactoryBean) {Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
filterChainDefinitionMap.put("/index.jsp", "anon");
filterChainDefinitionMap.put("/common/**", "anon");
filterChainDefinitionMap.put("/**/login/**", "anon");
filterChainDefinitionMap.put("/**", "authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
}
}
登录办法:
@RequestMapping(value = "login")
@ResponseBody
public Object login(@ModelAttribute("user")LoginUser user, HttpServletRequest request) {BaseResp resp = new BaseResp();
String access_token = ""+ IdUtils.id();
JSONObject jsonObject = new JSONObject();
/**
* 应用 Shiro 编写认证操作
*/
try {
//1. 获取 Subject
Subject subject = SecurityUtils.getSubject();
//2. 封装用户数据
UsernamePasswordToken token = new UsernamePasswordToken(user.getUserName(), CommonUtils.md5(user.getPassword()));
// UsernamePasswordToken token = new UsernamePasswordToken(user.getUserName(),user.getPassword());
//3. 执行登录办法
subject.login(token);
jsonObject.put("access_token",access_token);
jsonObject.put("user",rtnUser((BusinessUserPo)subject.getPrincipal()));
resp.setData(jsonObject);
} catch (UnknownAccountException e) {resp.setSuccess(false);
resp.setMsg(e.getMessage());
e.printStackTrace();} catch (IncorrectCredentialsException e) {resp.setSuccess(false);
resp.setMsg(e.getMessage());
e.printStackTrace();}catch (Exception e){resp.setSuccess(false);
resp.setMsg("零碎异样,请稍后再试");
e.printStackTrace();}
return resp;
}
前台页面应用:
jsp:
<%@taglib prefix="shiro" uri="http://shiro.apache.org/tags"%>
按钮权限:
<div class="layui-btn-container">
<shiro:hasPermission name="taskProgress:add">
<button class="layui-btn layui-btn-sm" data-type="addRec"> 增加 </button>
</shiro:hasPermission>
<shiro:hasPermission name="taskProgress:del">
<button class="layui-btn layui-btn-sm layui-btn-danger" data-type="delRec"> 删除 </button>
</shiro:hasPermission>
</div>