zoukankan      html  css  js  c++  java
  • springboot整合shiro实现登录认证以及授权

    1.添加shiro的依赖

    <dependency>
        <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-spring-boot-web-        
             starter</artifactId>
        <version>1.4.0</version>
    </dependency>    

    2.先创建一个Realm

    public class MyShiroRealm extends AuthorizingRealm {
        @Autowired
        private RoleService roleService;//角色模模块
        @Autowired
        private UserService userService;//用户模块
        @Autowired
        private PermissionService permissionService;//权限模块
        /**
         * 用户身份识别(登录")
         * @param authenticationToken
         * @return
         * @throws AuthenticationException
         */
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
            UsernamePasswordToken authToken = (UsernamePasswordToken) authenticationToken;
            // 获取用户输入的账号
            String userName = authToken.getUsername();
         //通过账号查找用户信息 User user
    = userService.selectUserOne(userName);// 将账户名,密码,盐值,getName()实例化到SimpleAuthenticationInfo中交给Shiro来管理 SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo( user, user.getPassWord(),
                                        //这里是设置的密码盐 ByteSource.Util.bytes(user.getSalt()), getName());
    return authenticationInfo; } /** * 访问控制。比如某个用户是否具有某个操作的使用权限 * @param principalCollection * @return */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(); String userName = (String) principalCollection.getPrimaryPrincipal(); if (userName == null) { log.error("授权失败,用户信息为空!!!"); return null; } try { //获取用户角色集 Set<String> listRole= roleService.findRoleByUsername(userName); simpleAuthorizationInfo.addRoles(listRole); //通过角色获取权限集 for (String role : listRole) { Set<String> permission= permissionService.findPermissionByRole(role); simpleAuthorizationInfo.addStringPermissions(permission); } return simpleAuthorizationInfo; } catch (Exception e) { log.error("授权失败,请检查系统内部错误!!!", e); } return simpleAuthorizationInfo; } }

    3.创建shiro的配置类

    @Configuration
    public class ShiroConfiguration {
       //配置自定义的Realm
        @Bean
        public MyShiroRealm myShiroRealm(HashedCredentialsMatcher matcher){
            MyShiroRealm myShiroRealm= new MyShiroRealm();
         //在这里配置密码加密
            myShiroRealm.setCredentialsMatcher(matcher);
            return myShiroRealm;
        }
      
    //将Realm注册到securityManager中 @Bean public DefaultWebSecurityManager securityManager(HashedCredentialsMatcher matcher){ DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(myShiroRealm(matcher)); return securityManager; } //如果没有此name,将会找不到shiroFilter的Bean @Bean(name = "shiroFilter") public ShiroFilterFactoryBean shiroFilter(org.apache.shiro.mgt.SecurityManager securityManager){ ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(securityManager); shiroFilterFactoryBean.setLoginUrl("/login"); //表示指定登录页面 shiroFilterFactoryBean.setSuccessUrl("/user/list"); // 登录成功后要跳转的链接 shiroFilterFactoryBean.setUnauthorizedUrl("/403"); //未授权页面 Map<String,String> filterChainDefinitionMap = new LinkedHashMap<>();//拦截器, 配置不会被拦截的链接 顺序判断 filterChainDefinitionMap.put("/login","anon"); //所有匿名用户均可访问到Controller层的该方法下 filterChainDefinitionMap.put("/userLogin","anon"); filterChainDefinitionMap.put("/image/**","anon"); filterChainDefinitionMap.put("/css/**", "anon"); filterChainDefinitionMap.put("/fonts/**","anon"); filterChainDefinitionMap.put("/js/**","anon"); filterChainDefinitionMap.put("/logout","logout"); filterChainDefinitionMap.put("/**", "authc"); //authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问 //filterChainDefinitionMap.put("/**", "user"); //user表示配置记住我或认证通过可以访问的地址 shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilterFactoryBean; } /** * SpringShiroFilter首先注册到spring容器 * 然后被包装成FilterRegistrationBean * 最后通过FilterRegistrationBean注册到servlet容器 * @return */ @Bean public FilterRegistrationBean delegatingFilterProxy(){ FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(); DelegatingFilterProxy proxy = new DelegatingFilterProxy(); proxy.setTargetFilterLifecycle(true); proxy.setTargetBeanName("shiroFilter"); filterRegistrationBean.setFilter(proxy); return filterRegistrationBean; } //设置cookie @Bean public SimpleCookie rememberMeCookie(){ //这个参数是cookie的名称,对应前端的checkbox的name=rememberMe SimpleCookie simpleCookie = new SimpleCookie("rememberMe"); //记住我cookie生效时间3个小时(单位秒) simpleCookie.setMaxAge(10800); return simpleCookie; } //cookie管理对象,记住我功能 @Bean public CookieRememberMeManager rememberMeManager(){ CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager(); cookieRememberMeManager.setCookie(rememberMeCookie()); return cookieRememberMeManager; } /** * 密码匹配凭证管理器(密码加密需要此配置) * @return */ @Bean(name = "hashedCredentialsMatcher") public HashedCredentialsMatcher hashedCredentialsMatcher() { HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(); hashedCredentialsMatcher.setHashAlgorithmName("MD5"); hashedCredentialsMatcher.setHashIterations(1024);// 设置加密次数 return hashedCredentialsMatcher; } //如果没有这两个配置,可能会授权失败,所以依赖中还需要配置aop的依赖 @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(HashedCredentialsMatcher matcher) { AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); authorizationAttributeSourceAdvisor.setSecurityManager(securityManager(matcher)); return authorizationAttributeSourceAdvisor; } @Bean @ConditionalOnMissingBean public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator(){ DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator=new DefaultAdvisorAutoProxyCreator(); defaultAdvisorAutoProxyCreator.setProxyTargetClass(true); return defaultAdvisorAutoProxyCreator; } }

    4.新建controller并写个登录的方法

      /**
         * 登录页面 这里对应shiro中配置的shiroFilter的登录方法
         * @return
         */
        @GetMapping("/login")
        public String login() {
            return "user/login";
        }
        //登录方法
    @PostMapping("/userLogin") public String toLogin( String userName,String passWord,Model model){ UsernamePasswordToken token =new UsernamePasswordToken(userName,passWord); Subject subject = SecurityUtils.getSubject(); try {
    //这里直接使用shiro的登录方法 subject.login(token);
    return "redirect:user/list";
    //登录失败时,会catch到你的异常,异常通过全局处理
         //model的msg需要在页面获取才能显示具体失败信息    }
    catch (UnknownAccountException e) { model.addAttribute("msg","该账号不存在"); } catch (IncorrectCredentialsException e) { model.addAttribute("msg","密码错误,请重试"); } catch (LockedAccountException e) { model.addAttribute("msg","该账户已被锁定,请联系管理员"); } catch (Exception e) { model.addAttribute("msg","登录失败"); } return "user/login"; }
    //添加
    @RequestMapping("/insertUser")
    @ResponseBody
    public int insertUser(User user){
    //将uuid设置为密码盐值
    String salt = UUID.randomUUID().toString().replaceAll("-","");
    SimpleHash simpleHash = new SimpleHash("MD5", user.getPassWord(), salt, 1024);
       //添加用户信息
    user.setPassWord(simpleHash.toHex()).setValid(1).setSalt(salt).setCreateTime(new Date()).setDel(0);
    return userMapper.insertSelective(user);
    }
     

    5.创建全局异常处理类

    @RestControllerAdvice
    public class GlobalExceptionHandle {
        @ExceptionHandler(ShiroException.class)
        public String doHandleShiroException(ShiroException se,Model model) {
            se.printStackTrace();
        //这里从登录方法抓取到异常之后会统一跳转到登录页面
        if(se instanceof UnknownAccountException){      //该账号不存在
        return "redirect:user/login";
        }
        if(se instanceof LockedAccountException){ //该账户已被锁定,请联系管理员
        return "redirect:user/login";
        }
        if(se instanceof IncorrectCredentialsException){//密码错误
        return "redirect:user/login";
        }
        if(se instanceof AuthorizationException){ //没有相应权限,请联系管理员
        return "redirect:user/login";
        }else{ //登录失败
         return "redirect:user/login";
        }
      }
    }

    权限需要开启权限注解才生效

        @GetMapping("/userPageList")  
        @ResponseBody
        @RequiresPermissions("user:view") //这里是用户对应的权限
        public PageList listPage(HttpServletRequest request){
            PageList pageList = new PageList();
            List<User> list= userService.findAllPage(request);//查询出的条数
            int totalCount = userService.countAll();//总记录数
            pageList.setRows(list);
            pageList.setTotal(totalCount);
            return pageList;
        }

    shiro用户角色和权限表

    -- Table structure for `sys_permission`
    DROP TABLE IF EXISTS `sys_permission`;
    CREATE TABLE `sys_permission` (
      `id` int(64) NOT NULL AUTO_INCREMENT,
      `name` varchar(32) DEFAULT NULL,
      `permission` varchar(32) DEFAULT NULL,
      `url` varchar(64) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
    
    -- ----------------------------
    -- Records of sys_permission
    -- ----------------------------
    INSERT INTO `sys_permission` VALUES ('1', '用户管理', 'user:view', 'user/userPageList');
    INSERT INTO `sys_permission` VALUES ('2', '用户添加', 'user:add', 'user/saveUser');
    INSERT INTO `sys_permission` VALUES ('3', '用户删除', 'user:del', 'user/delById');
    
    -- ----------------------------
    -- Table structure for `sys_role`
    -- ----------------------------
    DROP TABLE IF EXISTS `sys_role`;
    CREATE TABLE `sys_role` (
      `id` int(64) NOT NULL,
      `available` varchar(8) DEFAULT NULL,
      `description` varchar(32) DEFAULT NULL,
      `role` varchar(32) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    -- ----------------------------
    -- Records of sys_role
    -- ----------------------------
    INSERT INTO `sys_role` VALUES ('1', '1', '管理员', 'admin');
    INSERT INTO `sys_role` VALUES ('2', '1', 'VIP会员', 'vip');
    
    -- ----------------------------
    -- Table structure for `sys_role_permission`
    -- ----------------------------
    DROP TABLE IF EXISTS `sys_role_permission`;
    CREATE TABLE `sys_role_permission` (
      `permission_id` int(64) NOT NULL COMMENT '权限表主键',
      `role_id` int(64) NOT NULL COMMENT '角色表主键'
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    -- ----------------------------
    -- Records of sys_role_permission
    -- ----------------------------
    INSERT INTO `sys_role_permission` VALUES ('1', '1');
    INSERT INTO `sys_role_permission` VALUES ('2', '1');
    
    -- ----------------------------
    -- Table structure for `sys_user_role`
    -- ----------------------------
    DROP TABLE IF EXISTS `sys_user_role`;
    CREATE TABLE `sys_user_role` (
      `role_id` int(64) NOT NULL,
      `user_id` int(64) NOT NULL
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    -- ----------------------------
    -- Records of sys_user_role
    -- ----------------------------
    INSERT INTO `sys_user_role` VALUES ('1', '1');
    
    -- ----------------------------
    -- Table structure for `user_info`
    -- ----------------------------
    DROP TABLE IF EXISTS `user_info`;
    CREATE TABLE `user_info` (
      `id` int(64) NOT NULL AUTO_INCREMENT,
      `name` varchar(32) DEFAULT NULL,
      `password` varchar(64) DEFAULT NULL,
      `salt` varchar(64) DEFAULT NULL,
      `state` varchar(8) DEFAULT NULL,
      `username` varchar(32) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
    
    -- ----------------------------
    -- Records of user_info
    -- ----------------------------
    INSERT INTO `user_info` VALUES ('1', '管理员', 'd3c59d25033dbf980d29554025c23a75', '8d78869f470951332959580424d4bf4f', '1', 'admin');

    最后声明下!!!我的开发环境是windows10+JDK1.8+springboot2.1.7+shiro1.4.0

  • 相关阅读:
    360手机青春版原装充电器
    然并卵却很拉风!360超级充电器评测_天极网
    39元超值!360超级充电器拆解与评测
    99元紫米10000mAh移动电源开箱拆解
    自己DIY PCB电路板制作(简单方便快捷)
    Easy EDA:在线创客软件服务是未来的趋势 | 雷锋网
    EasyEDA
    我的那些年(9)~我来团队了,Mvc兴起了
    我的那些年(8)~去朋友公司做网站开发
    我的那些年(7)~第一份互联网工作
  • 原文地址:https://www.cnblogs.com/red-star/p/12063735.html
Copyright © 2011-2022 走看看