当前仓库属于暂停状态,部分功能使用受限,详情请查阅 仓库状态说明
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README
Apache-2.0

本框架最适用于前后端分离+分布式下的session共享的权限项目框架

tip:这是一个通用模板框架 可以适用于 前后端不分离 或者 前后端不分离 就算不是分布式下依旧可以,但是没必要.

2019/2/27 更新:重写shiro未授权或未登入的跳转方式 具体看step5

使用主体框架为: springboot+mybatis-plus+shiro+redis

框架简述:

0.本项目为多模块项目 有security模块(shiro-core 链接最底下),只有需要权限框架才需要引入(复制)该模块依赖.不然会出现没有实现类错误(已经@Autowired) 需要时候可以直接复制security框架或者引入shiro-core依赖.但是需要注意的是.springbootApplication包扫描需要扫描到.第二就是companyPropertis是从配置文件中读取,不可以没有.如果是复制的可以直接改前缀.引入依赖的就要重新install再引入

也就是说整体框架已经搭完成,各种登入配置接近完成.每个web或者App只需要自定义shiroConfig的登入拦截配置(必须) 和 userDetailServiceImpl(必须)实现里面相应的方法.框架已经加了日志可以直观看出来,具体可以看操作步骤0

每个依赖security模块时候需要自定义实现类.目前有表单登入,短信验证码登入,社交登入 各种配置需要 username login:company:xxx password xxx 下列例子(以下的company是为分隔符.用于分辨登入方式,company由配置文件中读取,可以叫abc那么分隔符就是abc)

(1) 表单 username form:company:linenxi password 123456 --表示 表单登入账号为 linenxi ,密码为 123456
(2) 验证码 username mobile:company:13587872968 password 9876 --表示 手机验证码登入手机号为 13587872968 ,验证码为 9876
(3) 社交登入 username social:company:abcdefg password openId:company:wx --表示 社交登入账号为下的 abcdefg,登入方式为openId下的wx登入(也有可能有些需要开放平台下就需要用openId改为unionId,qq登入就将wx改为qq)

1.背景 在最基础的shiro框架加前后端不分离技术下,浏览器都会在cookie中携带sessionId,每次访问服务器都会带上sessionId访问服务器.从而达到保持会话目的

2.衍生 在前后端分离技术下http请求都是无状态的 往往不采用cookie保存sessionId的方式而是用请求头中携带token.token中附带sessionId从而来保持会话目的

3.最终 再基于分布式架构下,session共享就是一个最主要的难点.一种办法是tomcat内session共享,但是耗费资源.第二种就是将session储存在redis中.不管多少服务器都是先访问redis.最终达成保持会话

3.1 tip:既然已经不是从服务器内的session来保持会话,那就是要重写获取session的方法.在经过源码断点之后发现最终是SessionDAO类获取session.也就是重写该类方法.

操作步骤

0 ShiroConfig实现需要拦截的配置以及登入失败等入口

@Configuration
@Slf4j
public class APPShiroConfig {

    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        Map<String, String> filterMap = new LinkedHashMap();
        filterMap.put("111111111111111111111/shiro/mp/login", "anon");
        filterMap.put("22222222222222222222/**", "authc");
        log.info("当前系统拦截模式为:{}", filterMap);
        shiroFilterFactoryBean.setUnauthorizedUrl("33333333333/admin/page/noAuth");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
        shiroFilterFactoryBean.setLoginUrl("4444444444444444444/shiro/mp/nologinCode");
        return shiroFilterFactoryBean;
    }
}

0 框架必须要的寻找用户实现类 表单登入需要用户名查找 验证码登入从redis查找 社交登入从社交表查找,. 只需要实现ShiroUserDetailService接口,整体框架就完成

@Component
@Slf4j
public class ShiroUserDetailServiceImpl implements ShiroUserDetailService {

    @Autowired
    private CompanyProperties companyProperties;

    @Autowired
    private MpUserInfoMapper mpUserInfoMapper;

    @Autowired
    private MpSocialInfoMapper mpSocialInfoMapper;

    @Autowired
    private MpShiroPermsInfoMapper mpShiroPermsInfoMapper;

    @Override
    public ShiroUserDetail getByMobile(String mobile) throws AuthenticationException {
        MpUserInfo mpUserInfo = mpUserInfoMapper.selectOne(new QueryWrapper<MpUserInfo>().eq("mobile", mobile));
        if (PublicUtil.isEmpty(mpUserInfo)) {
            log.error("未找到与该手机号相关联的用户 :mobile=[ {} ]", mobile);
            throw new AccountException("未找到与该手机号相关联的用户");
        }
        return this.filling(mpUserInfo);
    }

    @Override
    public ShiroUserDetail getByUserName(String username) throws AuthenticationException {
        MpUserInfo mpUserInfo = mpUserInfoMapper.selectOne(new QueryWrapper<MpUserInfo>().eq("username", username));
        if (PublicUtil.isEmpty(mpUserInfo)) {
            log.error("未找到该用户名对应的用户 :username=[ {} ]", username);
            throw new AccountException("未找到该用户名对应的用户");
        }
        return this.filling(mpUserInfo);
    }

    @Override
    public ShiroUserDetail getBySocialProvider(String itemId, String socialProviderId) throws AuthenticationException {
        String[] split = socialProviderId.split(":" + companyProperties.getLoginSplit() + ":");
        if (split.length!=2) {
            throw new PrefixNotFoundException("社交登入,没有分隔符");
        }
        String social = split[0]; // openId/unionId
        String socialUnderLine = PublicUtil.underline(new StringBuffer(social)).toString();
        String providerId = split[1]; //wx/qq
        log.warn("社交登入中的: social= [ {} 登入,主体为 {} ],providerId=[ {} ]", social,itemId, providerId);
        List<MpSocialInfo> mpSocialInfos = mpSocialInfoMapper.selectList(
                new QueryWrapper<MpSocialInfo>().eq(socialUnderLine, itemId).eq("provider_id", providerId));
        if (PublicUtil.isEmpty(mpSocialInfos)) {
            log.error("未找到社交登入的账号 :social=[ {} ],providerId=[ {} ]", social, providerId);
            throw new SocialUserNotFoundException("未找到对应的社交登入记录");
        }
        long userId = Long.parseLong(mpSocialInfos.iterator().next().getUserId());
        MpUserInfo mpUserInfo = mpUserInfoMapper.selectById(userId);
        return this.filling(mpUserInfo);
    }

    private ShiroUserDetail filling(MpUserInfo mpUserInfo) throws AuthenticationException {
        List<MpShiroPermsInfo> mpShiroPermsInfos = mpShiroPermsInfoMapper.selectList(new QueryWrapper<MpShiroPermsInfo>().eq("user_id", mpUserInfo.getId()));
        List<String> perms = Lists.newArrayList();
        if (PublicUtil.isNotEmpty(mpShiroPermsInfos)) {
            mpShiroPermsInfos.forEach(obj -> perms.add(obj.getPerms()));
            mpUserInfo.setPerms(perms);
            mpUserInfo.setMpShiroPermsInfoList(mpShiroPermsInfos);
        }
        log.warn("数据库查询成功 登入用户为 userId=[ {} ],用户名为:[ {} ]", mpUserInfo.getId().toString(), mpUserInfo.getUsername());
        log.warn("shiro框架识别用户名成功 < ================= < ============== < ");
        return new ShiroUserDetail(mpUserInfo.getId().toString(), mpUserInfo.getUsername(), mpUserInfo.getPassword(), mpUserInfo.getPerms());
    }
}

1.引入pom依赖

<dependency>
    <groupId>org.crazycake</groupId>
    <artifactId>shiro-redis</artifactId>
    <version>2.4.2.1-RELEASE</version>
</dependency>

2.配置session获得方式

@Bean
public SessionManager sessionManager() {
    //配置sessionId获取方式.这里用ajax请求头
    MySessionManager mySessionManager = new MySessionManager();
    //配置session获得方式 最终是SessionDAO类获取session会话.所以要重写
    mySessionManager.setSessionDAO(sessionDAO());
    return mySessionManager;
}

3.配置sessionDAO

@Bean
SessionDAO sessionDAO() {
    log.error("使用redis缓存");
    RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
    redisSessionDAO.setRedisManager(redisManager());
    log.info("设置redisSessionDAO");
    return redisSessionDAO;
}

4.配置redisManager

@Bean
public RedisManager redisManager() {
    RedisManager redisManager = new RedisManager();
    redisManager.setHost(host);
    redisManager.setPort(port);
    redisManager.setPassword(password);
    redisManager.setExpire(timeout);// 配置过期时间
    log.info("配置redis连接设置##########" + host + ":::" + port);
    return redisManager;
}

5.重写shiro未授权或未登入的跳转方式

原本shiro未授权或未登入是在ShiroFilterFactoryBean 设置   
shiroFilterFactoryBean.setUnauthorizedUrl("33333333333/admin/page/noAuth");
shiroFilterFactoryBean.setLoginUrl("4444444444444444444/shiro/mp/nologinCode");
但是这个方式是重定向方式,如果是前后端不分离也就是java控制页面控制器,并没有问题.
但是如果前后端分离之后,页面控制器权力在前端手中,我们是需要给予返回json中的code例如2000状态码判断是否登入或授权
而shiro默认跳转方式重定向,而前端get请求无法捕捉重定向方式,所以要重写以上2句代码对应的跳转方法
filter包下 
=> NoLoginFilter 未登入下的直接返回状态码 
    saveRequestAndRedirectToLogin
=> NoPermsFilter 未权限授权下的直接返回状态码
=> NoRolesFilter  未权限授权下的直接返回状态码 未授权需要重写2个跳转,因为未授权之前要先判断是否有登入,登入之后再判断是否授权
        @Override
        protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws IOException {
            Subject subject = getSubject(request, response);
            if (subject.getPrincipal() == null) {
                log.error("该用户在访问受角色保护资源时候未登入");
                //未登入
                ShiroURLFunction.saveRequestAndRedirectToLogin(request, response);
            } else {
                HttpServletRequest httpServletRequest= (HttpServletRequest) request;
                log.error("用户:[ {} ] 没有访问该角色资源 [ {} ]",ShiroUtils.getUser().getUsername(),httpServletRequest.getRequestURI());
                ShiroThreadLocalMap.put("noAuthError", new StringBuilder().append("用户:[ ")
                        .append(ShiroUtils.getUser().getUsername()).append(" ]")
                        .append("没有访问该角色资源 [ ").append(httpServletRequest.getRequestURI()).append(" ]"));
                ShiroURLFunction.saveRequestAndRedirectToNoAuth(request, response);
            }
            return false;
        }

shiro-core https://gitee.com/lexapps/shiro-core.git

shiro-frame https://gitee.com/lexapps/shiro-frame.git

Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

简介

APP-WEB 多模块应用下的shiro登入框架 适用于前后端分离以及session共享,APP与web共享一套shiro-security模块应用.但是可以自定义获取用户信息.APP与web分开管理.但是权限操作可以相同处理 展开 收起
Java
Apache-2.0
取消

发行版 (1)

全部

贡献者

全部

近期动态

加载更多
不能加载更多了
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化