springboot shiro认证授权

本文介绍了 springboot shiro认证授权

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

}
上一篇 下一篇


推荐文章

评论
说点什么吧?

发表评论

取消回复
  最新文章