springboot整合shiro框架学习

springboot整合shiro框架做用户认证与授权

springboot整合shiro框架的流程主要分为:

  1. 导入shiro依赖
    <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.7.1</version>
    </dependency>        
  2. 编写shiro配置类,其中shiroconfig类主要用于配置过滤器,管理器和自定义的认证鉴权类。userRealm类是自定义的认证鉴权类继承自AuthorizingRealm类。
    package com.codeyoung.shirodemo.config;/**
     * @author: ouououou
     * @date: 2021/11/3 14:17
     * @description:
     */
    
    import org.apache.shiro.realm.Realm;
    import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
    import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    import java.util.LinkedHashMap;
    import java.util.Map;
    
    /**
     * @ClassName ShiroConfig
     * @Description TODO
     * @Author ouououou
     * @Date 2021/11/3 14:17
     * @Version 1.0
     **/
    @Configuration
    public class ShiroConfig {
        //ShiroFilterFactoryBean DefaultWebSecurityManager  Realm
        @Bean
        public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Autowired DefaultWebSecurityManager defaultWebSecurityManager){
            ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
            //设置管理器
            shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
            //设置拦截器
            Map<String, String> map=new LinkedHashMap<>();
            //设置需要拦截的请求和内置的过滤器 anon:无需认证 authc:必须认证了才能通过 user:必须拥有记住我功能 perms:拥有某个资源的权限 role:拥有某个角色权限
            map.put("/user/**","authc");
            //可以在map中进行权限过滤 添加的过滤器类型为perms 表示拥有user:add权限的用户才可以访问/user/add页面
            map.put("/user/add","perms[user:add]");
            //设置未授权跳转页面
            shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized");
            shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
            shiroFilterFactoryBean.setLoginUrl("/toLogin");
            return shiroFilterFactoryBean;
        }
    
    
        @Bean
        public DefaultWebSecurityManager getDefaultWebSecurityManager(@Autowired UserRealm userRealm){
            DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
            defaultWebSecurityManager.setRealm(userRealm);
            return defaultWebSecurityManager;
        }
    
    
        @Bean
        public UserRealm getUserRealm(){
            return new UserRealm();
        }
    }
    package com.codeyoung.shirodemo.config;/**
     * @author: ouououou
     * @date: 2021/11/3 14:17
     * @description:
     */
    
    import com.sun.crypto.provider.PBEWithMD5AndDESCipher;
    import org.apache.catalina.User;
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authc.*;
    import org.apache.shiro.authc.credential.Md5CredentialsMatcher;
    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;
    
    /**
     * @ClassName UserRealm
     * @Description TODO
     * @Author ouououou
     * @Date 2021/11/3 14:17
     * @Version 1.0
     **/
    public class UserRealm  extends AuthorizingRealm {
        /**
         * @description 授权 用户认证后经过授权过滤会进入此方法,可在此方法中进行授权
         * @param principalCollection
         * @date 2021/11/3 14:25
         * @return org.apache.shiro.authz.AuthorizationInfo
         */
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
            SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
            //获取当前登录的用户为其授权
            Subject subject = SecurityUtils.getSubject();
            //用户经过认证后将其用户信息放入subject的principal中获取出来
            //User principal = (User) subject.getPrincipal();
            //通过用户的信息查询数据库中的权限为其授权
            simpleAuthorizationInfo.addStringPermission("");
            return simpleAuthorizationInfo;
        }
    
        /**
         * @description 认证 控制层调用login方法会进入此方法执行
         * @param authenticationToken
         * @date 2021/11/3 14:25
         * @return org.apache.shiro.authc.AuthenticationInfo
         */
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
            //将token转为保存用户名密码的token
            UsernamePasswordToken userToken = (UsernamePasswordToken) authenticationToken;
            //获取用户名
            String username = userToken.getUsername();
            //查询数据库获取用户信息
            //User user=userService.findUserByName(username);
            //通过用户名查询出对应的密码进行认证 模拟查询回来的密码
            String password="132";
            Md5CredentialsMatcher md5CredentialsMatcher = new Md5CredentialsMatcher();
    
            return new SimpleAuthenticationInfo("", "password", "");
        }
    }
  3. 当访问任意页面时会进入ShiroConfig类中的过滤器,验证访问该页面需要的认证要求。如果需要登录则会跳转到登录页面。
  4. 当前端发起登录请求,通过SecurityUtils获取到当前登录的用户,将用户的数据封装到一个UsernamePasswordToken中,执行subject的login方法会进入到自定义认证鉴权类的认证方法doGetAuthenticationInfo(),将方法参数的token转为配置了用户登录参数的token,取出用户名在数据库查询出用户信息后,通过shiro框架的SimpleAuthenticationInfo对象传入密码,shiro框架会对密码进行验证。
    @RequestMapping("/login")
        public String login(@RequestParam("username") String username,@RequestParam("password") String password,Model model){
            //获取当前登录用户
            Subject subject = SecurityUtils.getSubject();
            //封装用户登录数据
            UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username,password);
            //登录请求会进到认证方法中
            try {
                subject.login(usernamePasswordToken);
                return "index";
            }catch (UnknownAccountException e){
                model.addAttribute("msg","用户名错误");
                return "login";
            }catch (IncorrectCredentialsException e){
                model.addAttribute("msg","密码错误");
                return "login";
            }catch (AuthenticationException e) {
                e.printStackTrace();
                return "login";
            }
        }
  5. 登陆成功后访问页面,如果页面需要授权则会经过shiroConfig的过滤器跳转到授权的页面,并对用户进行授权。UserRealm类的doGetAuthorizationInfo方法可以对用户进行授权,通过SecurityUtils获取出当前登录的用户,查询数据库获得当前登录的用户的权限列表,再通过simpleAuthorizationInfo对象将用户的权限设置后返回。
    @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
            SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
            //获取当前登录的用户为其授权
            Subject subject = SecurityUtils.getSubject();
            //用户经过认证后将其用户信息放入subject的principal中获取出来
            //User principal = (User) subject.getPrincipal();
            //通过用户的信息查询数据库中的权限为其授权
            simpleAuthorizationInfo.addStringPermission("");
            simpleAuthorizationInfo.setObjectPermissions(new HashSet<>());
            return simpleAuthorizationInfo;
        }

     

posted @ 2021-11-03 17:06  迷茫的bug  阅读(270)  评论(0编辑  收藏  举报
1