zoukankan      html  css  js  c++  java
  • springboot 集成shiro

    首先看下shiro configuration 的配置,重要部分用红色标出了

    package cn.xiaojf.today.shiro.configuration;
    
    import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
    import cn.xiaojf.today.sys.security.credentials.RetryLimitHashedCredentialsMatcher;
    import cn.xiaojf.today.sys.security.filter.MyLogoutFilter;
    import cn.xiaojf.today.sys.security.filter.RoleAuthorizationFilter;
    import cn.xiaojf.today.sys.security.realm.UsernameRealm;
    import cn.xiaojf.today.sys.service.SysResService;
    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.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
    import org.springframework.boot.web.servlet.FilterRegistrationBean;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.filter.DelegatingFilterProxy;
    
    import javax.servlet.Filter;
    import java.util.LinkedHashMap;
    import java.util.Map;
    
    /**
     * shiro配置
     * @author xiaojf 2017/2/10 11:30.
     */
    @Configuration
    public class ShiroConfiguration {
        @Bean
        public FilterRegistrationBean filterRegistrationBean() {
            FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
            filterRegistrationBean.setFilter(new DelegatingFilterProxy("shiroFilter"));
            filterRegistrationBean.addInitParameter("targetFilterLifecycle", "true");
            filterRegistrationBean.setEnabled(true);
            filterRegistrationBean.addUrlPatterns("/*");
            return filterRegistrationBean;
        }
    
        @Bean
        public RetryLimitHashedCredentialsMatcher credentialsMatcher() {
            RetryLimitHashedCredentialsMatcher credentialsMatcher = new RetryLimitHashedCredentialsMatcher();
            credentialsMatcher.setHashAlgorithmName("sha");
            credentialsMatcher.setHashIterations(2);
            credentialsMatcher.setStoredCredentialsHexEncoded(true);
            credentialsMatcher.setRetryCount(5);
            credentialsMatcher.setRetryTime(1800000);
            return credentialsMatcher;
        }
    
        @Bean
        public UsernameRealm usernameRealm(RetryLimitHashedCredentialsMatcher credentialsMatcher) {
            UsernameRealm usernameRealm = new UsernameRealm();
            usernameRealm.setCredentialsMatcher(credentialsMatcher);
            usernameRealm.setCachingEnabled(true);
            return  usernameRealm;
        }
    
        @Bean
        public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
            return new LifecycleBeanPostProcessor();
        }
    
        @Bean
        public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
            DefaultAdvisorAutoProxyCreator daap = new DefaultAdvisorAutoProxyCreator();
            daap.setProxyTargetClass(true);
            return daap;
        }
    
        @Bean
        public DefaultWebSecurityManager securityManager(UsernameRealm usernameRealm) {
            DefaultWebSecurityManager dwsm = new DefaultWebSecurityManager();
            dwsm.setRealm(usernameRealm);
            return dwsm;
        }
    
        @Bean
        public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager defaultWebSecurityManager) {
            AuthorizationAttributeSourceAdvisor aasa = new AuthorizationAttributeSourceAdvisor();
            aasa.setSecurityManager(defaultWebSecurityManager);
            return aasa;
        }
    
        @Bean
        public MyLogoutFilter logoutFilter() {
            MyLogoutFilter myLogoutFilter = new MyLogoutFilter();
            myLogoutFilter.setRedirectUrl("/login/index");
            return myLogoutFilter;
        }
    
        @Bean(name = "shiroFilter")
        public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager,
                                                             MyLogoutFilter logoutFilter, ApplicationContext context) {
            ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
            shiroFilterFactoryBean.setSecurityManager(securityManager);
            shiroFilterFactoryBean.setLoginUrl("/login/index");
            shiroFilterFactoryBean.setUnauthorizedUrl("/login/index");
    
            Map<String, Filter> filters = new LinkedHashMap<>();
    //        filters.put("logout", logoutFilter);
            filters.put("role", new RoleAuthorizationFilter());
    
            shiroFilterFactoryBean.getFilters().putAll(filters);//加载自定义拦截器
    
            SysResService resService = context.getBean(SysResService.class);//只有通过这种方式才能获得resService,因为此处会优先于resService实例化
            loadShiroFilterChain(shiroFilterFactoryBean,resService);//加载拦截规则
            return shiroFilterFactoryBean;
        }
    
        private void loadShiroFilterChain(ShiroFilterFactoryBean shiroFilterFactoryBean,SysResService resService) {
            Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
         //默认拦截规则 filterChainDefinitionMap.put(
    "/login/index", "anon"); filterChainDefinitionMap.put("/error/403", "anon"); filterChainDefinitionMap.put("/error/404", "anon"); filterChainDefinitionMap.put("/error/500", "anon"); filterChainDefinitionMap.put("/login/auth", "anon"); filterChainDefinitionMap.put("/logout", "logout"); filterChainDefinitionMap.put("/plugins/**", "anon"); filterChainDefinitionMap.put("/css/**", "anon"); filterChainDefinitionMap.put("/js/**", "anon"); filterChainDefinitionMap.put("/images/**", "anon");      //用户自定义拦截规则 filterChainDefinitionMap = resService.loadFilterChainDefinitions(filterChainDefinitionMap);      //都不满足的时候,需要超级管理员权限才能访问 filterChainDefinitionMap.put("/**", "role[ROLE_SUPER]");      shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); } @Bean public ShiroDialect shiroDialect() {//thymeleaf 集成shiro使用,如果没有可以删除 return new ShiroDialect(); } }

    自定义realm,用于认证和授权

    package cn.xiaojf.today.sys.security.realm;
    
    import cn.xiaojf.today.base.constant.DataStatus;
    import cn.xiaojf.today.base.constant.SystemConstant;
    import cn.xiaojf.today.sys.entity.SysUser;
    import cn.xiaojf.today.sys.service.SysUserService;
    import org.apache.shiro.authc.*;
    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.util.ByteSource;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Lazy;
    
    import java.util.Set;
    
    /**
     * 根据用户名和密码校验登陆
     *
     * @author xiaojf 2016-01-07 16:05:55
     */
    public class UsernameRealm extends AuthorizingRealm {
    
        /**
         * 系统用户service
         */
        @Autowired
        @Lazy
        private SysUserService sysUserService;
    
        /**
         * 加载用户授权信息, 包括权限资源和角色用户组资源
         *
         * @author xiaojf 2016-01-07 16:05:55
         */
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
    
            // 登陆名
            String username = (String) principals.getPrimaryPrincipal();
            SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
    
            Set<String> roles = sysUserService.loadEnabledRolesByUsername(username);
    
            if (roles.contains(SystemConstant.ROLE_SUPER)) {
                authorizationInfo.addStringPermission("*");
            }else {
                // 加载权限资源
                authorizationInfo.setStringPermissions(sysUserService.loadEnabledPermissionsByUsername(username));
            }
    
            // 加载角色/用户组
            authorizationInfo.setRoles(roles);
    
            return authorizationInfo;
        }
    
        /**
         * 加载用户身份认证信息
         *
         * @author xiaojf 2016-01-07 16:05:55
         */
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
            String username = (String) token.getPrincipal();
    
            // 获取账号信息
            SysUser sysUser = sysUserService.getByUsername(username);
    
            if (sysUser == null) {
                throw new UnknownAccountException();    // 没找到帐号
            }
    
            if (sysUser.getStatus() == DataStatus.LOGIC_DELETE.getValue()) {
                throw new UnknownAccountException();    // 没找到帐号
            }
    
            if (sysUser.getStatus() == DataStatus.DISABLE.getValue()) {
                throw new LockedAccountException();    // 帐号锁定
            }
    
            SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(sysUser.getUsername(),
                    sysUser.getPwd(), ByteSource.Util.bytes(sysUser.getSalt()),
                    getName());
    
            return authenticationInfo;
        }
    
    }

    自定义登出过滤器

    package cn.xiaojf.today.sys.security.filter;
    
    import org.apache.shiro.web.filter.authc.LogoutFilter;
    
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.HttpServletRequest;
    import java.util.Date;
    
    /**
     * 自定义退出过滤器
     * @author xiaojf 294825811@qq.com
     *
     * 2015-3-20
     */
    public class MyLogoutFilter extends LogoutFilter {
        
        @Override
        protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
            return true;
        }
    }

    自定义权限校验过滤器

    package cn.xiaojf.today.sys.security.filter;
    
    import com.alibaba.fastjson.JSON;
    import cn.xiaojf.today.base.model.CommonResult;
    import org.apache.shiro.subject.Subject;
    import org.apache.shiro.util.CollectionUtils;
    import org.apache.shiro.util.StringUtils;
    import org.apache.shiro.web.filter.authz.AuthorizationFilter;
    import org.apache.shiro.web.util.WebUtils;
    
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.util.Set;
    
    /**
     * 自定义认证器,区分ajax请求
     * @author xiaojf 2017/2/10 11:30.
     */
    public class RoleAuthorizationFilter extends AuthorizationFilter {
    
        public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue)
                throws IOException {
    
            Subject subject = getSubject(request, response);
            String[] rolesArray = (String[]) mappedValue;
    
            if (rolesArray == null || rolesArray.length == 0) {
                // no roles specified, so nothing to check - allow access.
                return true;
            }
    
            Set<String> roles = CollectionUtils.asSet(rolesArray);
            for (String role : roles) {
                if (subject.hasRole(role)) {
                    return true;
                }
            }
            return false;
        }
    
        @Override
        protected boolean onAccessDenied(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
    
            HttpServletRequest httpServletRequest = (HttpServletRequest) request;
            HttpServletResponse httpServletResponse = (HttpServletResponse) response;
    
            Subject subject = getSubject(request, response);
    
            if (subject.getPrincipal() == null) {
                if ("XMLHttpRequest".equalsIgnoreCase(httpServletRequest.getHeader("X-Requested-With"))) {
                    httpServletResponse.setCharacterEncoding("UTF-8");
                    httpServletResponse.setHeader("Charset","UTF-8");
                    PrintWriter out = httpServletResponse.getWriter();
    
                    CommonResult result = new CommonResult(false);
                    result.setCode("401");
                    result.setMsg("请重新登录");
    
                    out.write(JSON.toJSONString(result));
                    out.flush();
                    out.close();
                } else {
    //                saveRequestAndRedirectToLogin(request, response);
                    String unauthorizedUrl = getUnauthorizedUrl();
                    WebUtils.issueRedirect(request, response, unauthorizedUrl);
                }
            } else {
                if ("XMLHttpRequest".equalsIgnoreCase(httpServletRequest.getHeader("X-Requested-With"))) {
                    httpServletResponse.setCharacterEncoding("UTF-8");
                    httpServletResponse.setHeader("Charset","UTF-8");
                    PrintWriter out = httpServletResponse.getWriter();
    
                    CommonResult result = new CommonResult(false);
                    result.setCode("403");
                    result.setMsg("没有足够的权限: "+((HttpServletRequest) request).getServletPath());
    
                    out.println(JSON.toJSONString(result));
                    out.flush();
                    out.close();
                } else {
                    String unauthorizedUrl = getUnauthorizedUrl();
                    if (StringUtils.hasText(unauthorizedUrl)) {
                        WebUtils.issueRedirect(request, response, unauthorizedUrl);
                    } else {
                        WebUtils.toHttp(response).sendError(403);
                    }
                }
            }
            return false;
        }
    }
  • 相关阅读:
    vscode 快捷键
    Nest 中在当前模块使用其他模块 service 的方式
    Elasticsearch:应用 Nodejs 来访问 Elasticsearch【转载】
    开始使用 Elasticsearch (1)[转载]
    SVO详细解读
    深度滤波器详细解读
    Google Cardboard的九轴融合算法——基于李群的扩展卡尔曼滤波
    相机IMU融合四部曲(三):MSF详细解读与使用
    相机IMU融合四部曲(二):误差状态四元数详细解读
    相机IMU融合四部曲(一):D-LG-EKF详细解读
  • 原文地址:https://www.cnblogs.com/xiaojf/p/6613666.html
Copyright © 2011-2022 走看看