spring 整合shiro ,并实现动态url 配置

来源:互联网 发布:sai中文mac 版 编辑:程序博客网 时间:2024/05/16 17:02

shiro 与Spring 结合

  • 数据库实现,参考RBAC角色权限控制的实现

  • maven 导入相关包

<!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-core -->        <dependency>            <groupId>org.apache.shiro</groupId>            <artifactId>shiro-core</artifactId>            <version>1.3.2</version>        </dependency>        <!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-web -->        <dependency>            <groupId>org.apache.shiro</groupId>            <artifactId>shiro-web</artifactId>            <version>1.3.2</version>        </dependency>        <!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-spring -->        <dependency>            <groupId>org.apache.shiro</groupId>            <artifactId>shiro-spring</artifactId>            <version>1.3.2</version>        </dependency>        <!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-ehcache -->        <dependency>            <groupId>org.apache.shiro</groupId>            <artifactId>shiro-ehcache</artifactId>            <version>1.3.2</version>        </dependency>
  • web.xml 配置
<filter>        <filter-name>shiroFilter</filter-name>        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>    </filter>    <filter-mapping>        <filter-name>shiroFilter</filter-name>        <url-pattern>/*</url-pattern>    </filter-mapping>
  • spring_shiro.xml
<!-- 自定义Realm -->    <bean id="myRealm" class="com.nzs.listener.MyShiroRealm"/>    <!-- 缓存管理 -->    <bean id="mycacheManager" class="org.apache.shiro.cache.MemoryConstrainedCacheManager"/>    <!-- 安全管理器 -->    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">        <property name="realm" ref="myRealm"/>        <property name="cacheManager" ref="mycacheManager"></property>    </bean>    <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>    <!-- Shiro过滤器 -->    <!--<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">-->    <bean id="shiroFilter" class="com.nzs.listener.ShiroPermissionFactory">        <property name="manageUserService" ref="manageUserService"/>        <!-- Shiro的核心安全接口,这个属性是必须的 -->        <property name="securityManager" ref="securityManager"/>        <!-- 身份认证失败,则跳转到登录页面的配置 -->        <property name="loginUrl" value="/login.jsp"/>        <!-- 登录成功跳转页面的配置 -->        <property name="successUrl" value="/index"/>        <!-- 权限认证失败,则跳转到指定页面 -->        <property name="unauthorizedUrl" value="/norole.jsp"/>        <!-- Shiro连接约束配置,即过滤链的定义 -->        <property name="filterChainDefinitions">            <value>                /manageUser/login=anon                <!--/** = authc-->            </value>        </property>    </bean>
  • 自定义的realm
public class MyShiroRealm extends AuthorizingRealm {    static IManageUserService manageUserService;    public static final String SESSION_USER_KEY = "temp";    /**     * 授权查询回调函数, 进行鉴权但缓存中无用户的授权信息时调用,负责在应用程序中决定用户的访问控制的方法     */    @Override    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {    //可自定义实现内容        SecurityUtils.getSubject().getSession()     .getAttribute(OneballShiroRealm.SESSION_USER_KEY);        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();        return info;    }    /**     * 认证回调函数,登录信息和用户验证信息验证     */    @Override    protected AuthenticationInfo doGetAuthenticationInfo(            AuthenticationToken authcToken) throws AuthenticationException {        //判断 manageUserService 是否为空        if (manageUserService == null) {            manageUserService = (ManageUserService) ApplicationContextUtil.getBean("manageUserService");        }        UsernamePasswordToken token = (UsernamePasswordToken) authcToken;        String userName = token.getUsername();        String passWord = String.valueOf(token.getPassword());        ManageUser manageUser = manageUserService.login(userName, passWord);        if (manageUser == null) {            return null; // 异常处理,找不到数据        }        Subject subject =  SecurityUtils.getSubject();        //shiro session        Session session = SecurityUtils.getSubject().getSession();        session.setTimeout(60 * 60 * 3 * 1000);        session.setAttribute(OneballShiroRealm.SESSION_USER_KEY, manageUser);        //当前 Realm 的 name        String realmName = this.getName();        //登陆的主要信息: 可以是一个实体类的对象, 但该实体类的对象一定是根据 token 的 username 查询得到的.        Object principal = authcToken.getPrincipal();        return new SimpleAuthenticationInfo(principal, passWord, realmName);    }    public IManageUserService getManageUserService() {        return manageUserService;    }    public void setManageUserService(IManageUserService manageUserService) {        this.manageUserService = manageUserService;    }}
  • 继承ShiroFilterFactoryBean,实现从数据库动态加载权限信息
public class ShiroPermissionFactory extends ShiroFilterFactoryBean {    private ManageUserService manageUserService;    /**记录配置中的过滤链*/    public static String definition="";    /**     * 初始化设置过滤链     */    @Override    public void setFilterChainDefinitions(String definitions) {//        String token =  manageUserService.getAdminToken(0);        //可从数据库读取后,添加至过滤链,参考此处已注释的代码        definition = definitions;//记录配置的静态过滤链//        List<Permission> permissions = permissService.findAll();        Map<String, String> otherChains = new HashMap<String,String>();//        permissions.forEach(permiss->{//            //perms.add(e)            otherChains.put("/discover/newstag", "authc,roles[user,admin]");//        });        //加载配置默认的过滤链        Ini ini = new Ini();        ini.load(definitions);        Ini.Section section = ini.getSection(IniFilterChainResolverFactory.URLS);        if (CollectionUtils.isEmpty(section)) {            section = ini.getSection(Ini.DEFAULT_SECTION_NAME);        }        //加上数据库中过滤链        section.putAll(otherChains);        setFilterChainDefinitionMap(section);    }    public ManageUserService getManageUserService() {        return manageUserService;    }    public void setManageUserService(ManageUserService manageUserService) {        this.manageUserService = manageUserService;    }}
  • FilterChainDefinitionsService实现,无需部署,重新加载权限
@Servicepublic class FilterChainDefinitionsService implements IFilterChainDefinitionsService {    @Autowired    private ShiroPermissionFactory permissFactory;    @Override    public void reloadFilterChains() {        synchronized (permissFactory) {   //强制同步,控制线程安全            AbstractShiroFilter shiroFilter = null;            try {                shiroFilter = (AbstractShiroFilter) permissFactory.getObject();                PathMatchingFilterChainResolver resolver = (PathMatchingFilterChainResolver) shiroFilter                        .getFilterChainResolver();                // 过滤管理器                DefaultFilterChainManager manager = (DefaultFilterChainManager) resolver.getFilterChainManager();                // 清除权限配置                manager.getFilterChains().clear();                permissFactory.getFilterChainDefinitionMap().clear();                // 重新设置权限                permissFactory.setFilterChainDefinitions(ShiroPermissionFactory.definition);//传入配置中的filterchains                Map<String, String> chains = permissFactory.getFilterChainDefinitionMap();                //重新生成过滤链                if (!CollectionUtils.isEmpty(chains)) {                    chains.forEach((url, definitionChains) -> {                        manager.createChain(url, definitionChains.trim().replace(" ", ""));                    });                }                // manager.addToChain("/discover/banner", "perms", "sssss");            } catch (Exception e) {                e.printStackTrace();            }        }    }}
  • 登录验证的实现
 //示例代码,未实现加密验证 private String loginUser(ManageUser user) {//        if (isRelogin(user)) {//            // 如果已经登陆,无需重新登录//            return "success";//        }        return shiroLogin(user); // 调用shiro的登陆验证    }    private String shiroLogin(ManageUser user) {        UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(), user.getPassword().toCharArray(), null);//        token.setRememberMe(true);        // shiro登陆验证        try {//            System.out.println(SecurityUtils.getSubject());            SecurityUtils.getSubject().login(token);        } catch (UnknownAccountException ex) {            return "用户不存在或者密码错误!";        } catch (IncorrectCredentialsException ex) {            return "用户不存在或者密码错误!";        }catch (ExcessiveAttemptsException ex) {            return "账号或密码错误次数过多,请稍后重试!";        } catch (AuthenticationException ex) {            return ex.getMessage(); // 自定义报错信息        } catch (Exception ex) {            ex.printStackTrace();            return "内部错误,请重试!";        }        return "success";    }    private boolean isRelogin(ManageUser user) {        Subject us = SecurityUtils.getSubject();        if (us.isAuthenticated()) {            return true; // 参数未改变,无需重新登录,默认为已经登录成功        }        return false; // 需要重新登陆    }
1 0
原创粉丝点击