1 2 3 4

springboot shiro认证授权

shiro必备表:用户,角色,权限     1:1:n   其中一种(可变)

------------------------------------------------------------------

shiro配置(类似于ssm中的xml配置)

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);
}

}
 
posted @ 2017-12-14 17:22  一缕清风丶  阅读(4725)  评论(0编辑  收藏  举报