• springboot整合shiro的使用


    shiro的原理已经有博客了,自己写可以问度娘

    参考https://www.cnblogs.com/liyinfeng/p/8033869.html

    此处直接描述实际使用

    一、pom.xml引包

     <!--shiro-->
            <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-spring</artifactId>
                <version>1.3.2</version>
            </dependency>

    二、三件套

    ShiroConfig 
    @Configuration
    public class ShiroConfig {
        @Bean
        public ShiroFilterFactoryBean shirFilter(DefaultWebSecurityManager securityManager) {
            System.out.println("ShiroConfiguration.shirFilter()");
            ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
            shiroFilterFactoryBean.setSecurityManager(securityManager);
            //拦截器.
            Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String,String>();
            // 配置不会被拦截的链接 顺序判断
            /**静态文件css及图片*/
            filterChainDefinitionMap.put("/static/**", "anon");
            /**webservice服务*/
            filterChainDefinitionMap.put("/services/**", "anon");
            filterChainDefinitionMap.put("/token/**", "anon");
            filterChainDefinitionMap.put("/swagger-ui.html", "anon");
            filterChainDefinitionMap.put("/webjars/**", "anon");
            filterChainDefinitionMap.put("/v2/**", "anon");
            filterChainDefinitionMap.put("/swagger-resources/**", "anon");
    
            //配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了
            filterChainDefinitionMap.put("/logout", "logout");
            //<!-- 过滤链定义,从上向下顺序执行,一般将/**放在最为下边 -->:这是一个坑呢,一不小心代码就不好使了;
            //<!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问-->
            filterChainDefinitionMap.put("/**", "authc");
            // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
            shiroFilterFactoryBean.setLoginUrl("/login");
            // 登录成功后要跳转的链接
            shiroFilterFactoryBean.setSuccessUrl("/index");
    
            //未授权界面;
            shiroFilterFactoryBean.setUnauthorizedUrl("/403");
            shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
            return shiroFilterFactoryBean;
        }
    
        @Bean
        public MyShiroRealm myShiroRealm(){
            MyShiroRealm myShiroRealm = new MyShiroRealm();
            return myShiroRealm;
        }
    
    
        @Bean
        public DefaultWebSecurityManager securityManager(){
                DefaultWebSecurityManager securityManager =  new DefaultWebSecurityManager();
            securityManager.setRealm(myShiroRealm());
            return securityManager;
        }
    }
    MyShiroRealm 
    @Slf4j
    public class MyShiroRealm extends AuthorizingRealm {
    
        @Autowired
        private UserInfoService userInfoService;
        /***授权方法*/
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {
            log.info("开始授权 --> MyShiroRealm.doGetAuthorizationInfo()");
            SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
            UserInfo userInfo  = (UserInfo)principal.getPrimaryPrincipal();
            for(SysRole role:userInfo.getRoleList()){
                authorizationInfo.addRole(role.getRole());
                for(SysPermission p:role.getPermissions()){
                    authorizationInfo.addStringPermission(p.getPermission());
                }
            }
            log.info("结束成功!");
            return authorizationInfo;
        }
    
        /**认证方法*/
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
            log.info("开始认证 --> MyShiroRealm.doGetAuthenticationInfo()");
            //获取用户的输入的账号.
            String username = (String)token.getPrincipal();
            System.out.println(token.getCredentials());
            //通过username从数据库中查找 User对象,如果找到,没找到.
            //实际项目中,这里可以根据实际情况做缓存,如果不做,Shiro自己也是有时间间隔机制,2分钟内不会重复执行该方法
            log.info("认证 --> 通过账户查询入参"+username);
            UserInfo userInfo = userInfoService.findByUsername(username);
            log.info("认证 --> 通过账户查询出参"+ JSON.toJSONString(userInfo));
            if(userInfo == null){
                log.info("认证失败!");
                return null;
            }
            SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
                    userInfo, //用户名
                    userInfo.getPassword(), //密码
                    ByteSource.Util.bytes(userInfo.getSalt()),//salt=username+salt
                    getName()  //realm name
            );
            log.info("认证成功!");
            return authenticationInfo;
        }
    }

    给shiro添加token,这时token中的用户才会执行认证授权的流程

        @ApiOperation("登陆获取token")
        @PostMapping("/login")
        @LoginToken
        public Object login(@RequestParam("username") String username, @RequestParam("password") String password) {
    
            JSONObject jsonObject = new JSONObject();
            UserInfo userInfo = userInfoService.findByUsername(username);
            if (userInfo == null) {
                jsonObject.put("message", "登录失败,用户不存在");
                return jsonObject;
            } else {
                EncryptUtil encryptUtil = EncryptUtil.getInstance();
                String passcode = encryptUtil.MD5(encryptUtil.Base64Encode(password) + userInfo.getSalt());
                //校验登陆密码加盐的一致性
                if (!userInfo.getPassword().equals(passcode)) {
                    jsonObject.put("message", "登录失败,密码错误");
                    return jsonObject;
                } else {
                    //shiro的token
                    //添加用户认证信息
                    Subject subject = SecurityUtils.getSubject();
                    UsernamePasswordToken shiroToken = new UsernamePasswordToken(userInfo.getUsername(),userInfo.getPassword());
                    //进行验证,这里可以捕获异常,然后返回对应信息
                    subject.login(shiroToken);
    
                    SignInReq sign = new SignInReq();
                    sign.setId(Integer.toString(userInfo.getUid()));
                    sign.setUserName(userInfo.getUsername());
                    //此处的密码是加盐加密过后的
                    sign.setPassword(userInfo.getPassword());
                    long now = System.currentTimeMillis();
                    String dateStr = DateUtil.parseDateToStr(new Date(now+expireTime), DateUtil.DATE_TIME_FORMAT_YYYY_MM_DD_HH_MI_SS);
                    String token = JwtTokenUtil.createJWT(expireTime, sign);
                    jsonObject.put("token", token);
                    jsonObject.put("expireTime",dateStr);
                    jsonObject.put("sign", sign);
                    return jsonObject;
                }
            }
        }

    当然权限crud的自己来一套

    最后就可以用了,哈哈

  • 相关阅读:
    chrome新版本flash无法在http网站上运行的解决办法
    SSO单点登录三种情况的实现方式详解(转载)
    解决请求筛选模块被配置为拒绝包含的查询字符串过长的请求(原创)
    更改mysql默认字符集 (转载)
    用TextWriterTraceListener实现log文件记录 (转载)
    PO BO VO DTO POJO DAO概念及其作用
    SqlServer 的一个坑
    关于windows服务注册的问题
    原生js的数组除重复
    ES6 箭头函数下的this指向和普通函数的this对比
  • 原文地址:https://www.cnblogs.com/h-c-g/p/11018415.html
Copyright © 2020-2023  润新知