shiro必備表:用戶,角色,權限 1:1:n 其中一種(可變)css
------------------------------------------------------------------html
shiro配置(相似於ssm中的xml配置)java
package cn.xydata.config.shiro;
import cn.xydata.entity.system.Permission;
import cn.xydata.service.impl.system.PermisssionServiceImpl;
import cn.xydata.service.system.PermissionService;
import org.apache.shiro.cache.ehcache.EhCacheManager;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@Configuration
public class ShiroConfig {
private static final Logger logger = LoggerFactory.getLogger(ShiroConfig.class);
@Bean(name="permissionService")
public PermissionService getPermissionService(){
return new PermisssionServiceImpl();
}
@Bean(name = "shiroEhcacheManager")
public EhCacheManager getEhCacheManager() {
EhCacheManager em = new EhCacheManager();
em.setCacheManagerConfigFile("classpath:ehcache.xml");
return em;
}
@Bean(name = "myShiroRealm")
public MyShiroRealm getShiroRealm() {
MyShiroRealm realm = new MyShiroRealm();
realm.setCacheManager(getEhCacheManager());
return realm;
}
@Bean(name = "lifecycleBeanPostProcessor")
public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
@Bean
public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator daap = new DefaultAdvisorAutoProxyCreator();
daap.setProxyTargetClass(true);
return daap;
}
@Bean(name = "securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager() {
DefaultWebSecurityManager dwsm = new DefaultWebSecurityManager();
dwsm.setRealm(getShiroRealm());
dwsm.setCacheManager(getEhCacheManager());
return dwsm;
}
@Bean
public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor() {
AuthorizationAttributeSourceAdvisor aasa = new AuthorizationAttributeSourceAdvisor();
aasa.setSecurityManager(getDefaultWebSecurityManager());
return aasa;
}
private void loadShiroFilterChain(ShiroFilterFactoryBean shiroFilterFactoryBean){
//關聯數據庫權限
List<Permission> Permissions=getPermissionService().getPermissions();
logger.info(String.valueOf(Permissions.size()));
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
for (Permission permission : Permissions) {
filterChainDefinitionMap.put(permission.getPageUrl(),"authc,perms["+permission.getId()+"]");
}
//放行靜態資源和登錄界面
filterChainDefinitionMap.put("/login", "anon");
filterChainDefinitionMap.put("/css/**", "anon");
filterChainDefinitionMap.put("/js/**", "anon");
filterChainDefinitionMap.put("/bootstrap/**", "anon");
filterChainDefinitionMap.put("/img/**", "anon");
filterChainDefinitionMap.put("/dist/**", "anon");
filterChainDefinitionMap.put("/plugins/**", "anon");
filterChainDefinitionMap.put("/**", "authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
}
//shiro攔截
@Bean(name = "shiroFilter")
public ShiroFilterFactoryBean getShiroFilterFactoryBean() {
ShiroFilterFactoryBean shiroFilterFactoryBean=null;
try {
shiroFilterFactoryBean = new MyShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(getDefaultWebSecurityManager());
shiroFilterFactoryBean.setLoginUrl("/login");
shiroFilterFactoryBean.setSuccessUrl("/index.html");
shiroFilterFactoryBean.setUnauthorizedUrl("/403");
loadShiroFilterChain(shiroFilterFactoryBean);
} catch (Exception e) {
e.printStackTrace();
}
return shiroFilterFactoryBean;
}
}
-----------------------------------------------------------------------------------------------------------
自定義ShiroRealm,實現對自定義數據表的操做
package cn.xydata.config.shiro;
import cn.xydata.entity.system.User;
import cn.xydata.mapper.system.UserMapper;
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
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.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import tk.mybatis.mapper.entity.Example;
import javax.annotation.PostConstruct;
import java.util.Set;
public class MyShiroRealm extends AuthorizingRealm {
private static final Logger logger = LoggerFactory.getLogger(MyShiroRealm.class);
private static final String ALGORITHM = "MD5";
@Autowired
private UserMapper userMapper;
@PostConstruct
public void initCredentialsMatcher() {
HashedCredentialsMatcher matcher = new HashedCredentialsMatcher(ALGORITHM);
setCredentialsMatcher(matcher);
}
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
logger.info("##################執行Shiro受權##################");
String username= (String)super.getAvailablePrincipal(principalCollection);
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
Set<String> roles = userMapper.findUserRoles(username);
authorizationInfo.setRoles(roles);
Set<String> permissions = userMapper.findUserPermissions(username);
authorizationInfo.setStringPermissions(permissions);
return authorizationInfo;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken authenticationToken) throws AuthenticationException {
//認證
UsernamePasswordToken token=(UsernamePasswordToken) authenticationToken;
logger.info("驗證當前Subject時獲取到token爲:" + ReflectionToStringBuilder.toString(token, ToStringStyle.MULTI_LINE_STYLE));
String username = (String) token.getPrincipal();
User user=userMapper.findByUsername(username);
if (user==null) {
throw new UnknownAccountException();//沒找到賬號
}
Subject currentUser = SecurityUtils.getSubject();
currentUser.getSession().setAttribute("userid", user.getId());
currentUser.getSession().setAttribute("isadmin", user.getAdmin());
currentUser.getSession().setAttribute("username", username);
if (Boolean.TRUE.equals(user.getLocked())) {
throw new LockedAccountException(); //賬號鎖定
}
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
user.getUsercode(),
user.getPasswd(),
getName()
);
/* SimpleByteSource sbs=new SimpleByteSource(user.getUsercode().getBytes());
authenticationInfo.setCredentialsSalt(sbs);*/
return authenticationInfo;
}
}
-----------------------------------------------------------------------------------------------------------
//自定義攔截工廠
package cn.xydata.config.shiro;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.mgt.FilterChainManager;
import org.apache.shiro.web.filter.mgt.FilterChainResolver;
import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
import org.apache.shiro.web.mgt.WebSecurityManager;
import org.apache.shiro.web.servlet.AbstractShiroFilter;
import org.springframework.beans.factory.BeanInitializationException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
public class MyShiroFilterFactoryBean extends ShiroFilterFactoryBean {
private Set<String> ignoreExt;
public MyShiroFilterFactoryBean() {
super();
ignoreExt = new HashSet<>();
ignoreExt.add(".jpg");
ignoreExt.add(".png");
ignoreExt.add(".gif");
ignoreExt.add(".bmp");
ignoreExt.add(".js");
ignoreExt.add(".css");
}
@Override
protected AbstractShiroFilter createInstance() throws Exception {
SecurityManager securityManager = getSecurityManager();
if (securityManager == null) {
String msg = "SecurityManager property must be set.";
throw new BeanInitializationException(msg);
}
if (!(securityManager instanceof WebSecurityManager)) {
String msg = "The security manager does not implement the WebSecurityManager interface.";
throw new BeanInitializationException(msg);
}
FilterChainManager manager = createFilterChainManager();
PathMatchingFilterChainResolver chainResolver = new PathMatchingFilterChainResolver();
chainResolver.setFilterChainManager(manager);
return new MSpringShiroFilter((WebSecurityManager) securityManager, chainResolver);
}
private final class MSpringShiroFilter extends AbstractShiroFilter {
protected MSpringShiroFilter(WebSecurityManager webSecurityManager, FilterChainResolver resolver) {
super();
if (webSecurityManager == null) {
throw new IllegalArgumentException("WebSecurityManager property cannot be null.");
}
setSecurityManager(webSecurityManager);
if (resolver != null) {
setFilterChainResolver(resolver);
}
}
@Override
protected void doFilterInternal(ServletRequest servletRequest, ServletResponse servletResponse,
FilterChain chain) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest)servletRequest;
String str = request.getRequestURI().toLowerCase();
boolean flag = true;
int idx = 0;
if(( idx = str.indexOf(".")) > 0){
str = str.substring(idx);
if(ignoreExt.contains(str.toLowerCase()))
flag = false;
}
if(flag){
super.doFilterInternal(servletRequest, servletResponse, chain);
}else{
chain.doFilter(servletRequest, servletResponse);
}
}
}
}
-----------------------------------------------------------------------------------------
shiro的實例應用
@ResponseBody()@RequestMapping(value = "/login",method = RequestMethod.POST)public Response login( @RequestParam(value="userName",required=false,defaultValue="") String userName, @RequestParam(value="passWord",required=false,defaultValue="") String passWord, @RequestParam(value="rememberMe",required=false,defaultValue="false") boolean rememberMe, RedirectAttributes redirectAttributes) { UsernamePasswordToken token = new UsernamePasswordToken(userName, passWord,rememberMe); Subject currentUser = SecurityUtils.getSubject(); try { logger.info("對用戶[" + userName + "]進行登陸驗證..驗證開始"); currentUser.login(token); logger.info("對用戶[" + userName + "]進行登陸驗證..驗證經過"); }catch(UnknownAccountException uae){ logger.info("對用戶[" + userName + "]進行登陸驗證..驗證未經過,未知帳戶"); redirectAttributes.addFlashAttribute("message", "用戶名不存在"); return new Response(ExceptionMsg.LoginNameNotExists); }catch(IncorrectCredentialsException ice){ logger.info("對用戶[" + userName + "]進行登陸驗證..驗證未經過,錯誤的憑證"); redirectAttributes.addFlashAttribute("message", "密碼不正確"); return new Response(ExceptionMsg.PassWordError); }catch(LockedAccountException lae){ logger.info("對用戶[" + userName + "]進行登陸驗證..驗證未經過,帳戶已鎖定"); redirectAttributes.addFlashAttribute("message", "帳戶已鎖定"); return new Response(ExceptionMsg.UserLock); }catch(ExcessiveAttemptsException eae){ logger.info("對用戶[" + userName + "]進行登陸驗證..驗證未經過,錯誤次數過多"); redirectAttributes.addFlashAttribute("message", "用戶名或密碼錯誤次數過多"); return new Response(ExceptionMsg.LoginNameOrPassWordError); }catch(AuthenticationException ae){ logger.info("對用戶[" + userName + "]進行登陸驗證..驗證未經過,堆棧軌跡以下"); ae.printStackTrace(); redirectAttributes.addFlashAttribute("message", "用戶名或密碼不正確"); return new Response(ExceptionMsg.LoginNameOrPassWordError); } if(currentUser.isAuthenticated()){ httpSession.setAttribute("username", currentUser.getPrincipal()); return new Response(ExceptionMsg.SUCCESS); }else{ return new Response(ExceptionMsg.FAILED); }}