zoukankan      html  css  js  c++  java
  • shiro认证

    认证

    固定数据

    Realm

        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
            String principal = (String) authenticationToken.getPrincipal();
            if("admin".equals(principal)){
                return new SimpleAuthenticationInfo("","123",this.getName());
            }
            return null;
        }

    配置类

    配置类中设置登录路径

            //指定登录页面
            shiroFilterFactoryBean.setLoginUrl("/tologin");

    放行登录操作的URL

    filterChainDefinitionMap.put("/login", "anon");

    自定义登录页面

    html

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <form th:action="@{/login}" >
        用户名:<input type="text" name="username"/>
        密码:<input type="password" name="password"/>
        <input type="submit" value="登录"/>
    </form>
    </body>
    </html>

    controller

        @GetMapping("/tologin")
        public String tologin(){
            return "login";
        }

    登录操作

        @RequestMapping("/login")
        public String login(String username,String password){
            Subject subject = SecurityUtils.getSubject();
            try {
                subject.login(new UsernamePasswordToken(username,password));
                return "index";
            } catch (AuthenticationException e) {
                e.printStackTrace();
                return "login";
            }
        }

    数据库数据

    数据准备

    CREATE TABLE `t_user`  (
      `USER_ID` BIGINT(0) NOT NULL AUTO_INCREMENT COMMENT '用户ID',
      `USERNAME` VARCHAR(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '登录名',
      `NAME` VARCHAR(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '用户名',
      `PASSWORD` VARCHAR(128) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '密码',
      `EMAIL` VARCHAR(128) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '邮箱',
      `MOBILE` VARCHAR(20) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '联系电话',
      `STATUS` CHAR(1) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '状态 0无效 1有效',
      `LAST_LOGIN_TIME` DATETIME(0) NULL DEFAULT NULL COMMENT '最近访问时间',
      `SSEX` CHAR(1) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '性别 0男 1女 2保密',
      `DESCRIPTION` VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '描述',
      `AVATAR` VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '用户头像',
      `FIRST_LANDING` CHAR(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT '首次登陆(0:首次登陆,1:非首次登陆)',
      `ROLE_ID` BIGINT(0) NULL DEFAULT NULL COMMENT '角色id',
      `HOSPITAL_PERM` VARCHAR(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '医院参照权限(1:全国;2:省指定;3:市指定;4:医院指定)',
      `OPEN_ID` VARCHAR(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '微信推送ID',
      `DELETE_FLAG` TINYINT(0) NOT NULL COMMENT '删除标志',
      `CREATE_TIME` DATETIME(0) NOT NULL COMMENT '创建时间',
      `CREATE_USER` VARCHAR(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '创建人',
      `MODIFY_TIME` DATETIME(0) NOT NULL COMMENT '修改时间',
      `MODIFY_USER` VARCHAR(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '修改人',
      PRIMARY KEY (`USER_ID`) USING BTREE,
      INDEX `t_user_index1`(`USER_ID`, `NAME`, `USERNAME`, `MOBILE`, `STATUS`, `CREATE_TIME`) USING BTREE
    ) ENGINE = INNODB AUTO_INCREMENT = 68 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = COMPACT;
    
    
    
    INSERT INTO `t_user`(`USER_ID`, `USERNAME`, `NAME`, `PASSWORD`, `EMAIL`, `MOBILE`, `STATUS`, `LAST_LOGIN_TIME`, `SSEX`, `DESCRIPTION`, `AVATAR`, `FIRST_LANDING`, `ROLE_ID`, `HOSPITAL_PERM`, `OPEN_ID`, `DELETE_FLAG`, `CREATE_TIME`, `CREATE_USER`, `MODIFY_TIME`, `MODIFY_USER`) 
    VALUES (1, 'admin', '超级管理员', '202cb962ac59075b964b07152d234b70', 'aaa@hotmail.com', '17314941691', '1', '2021-07-09 16:17:56', '2', '超级管理员', '20180414170003.jpg', '1', 1, NULL, NULL, 0, '2017-12-27 15:47:19', 'sys', '2021-07-05 09:40:44', 'admin');
    View Code

    密码:123的md5加密

    添加依赖

    shiro依赖、数据库驱动依赖、mybatis-plus依赖、生成器依赖(注意:模板依赖)

        <dependencies>
            <!--shiro-spring 依赖 -->
            <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-spring</artifactId>
                <version>1.7.1</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-thymeleaf</artifactId>
            </dependency>
            <!--mysql 依赖 -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>8.0.26</version>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.18.20</version>
            </dependency>
            <!--mybatis-plus 依赖 -->
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-boot-starter</artifactId>
                <version>3.2.0</version>
            </dependency>
            <!--mybatis-plus的生成器 依赖 -->
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-generator</artifactId>
                <version>3.4.1</version>
            </dependency>
            <!--mybatis-plus的生成器中模板 依赖 -->
            <dependency>
                <groupId>org.freemarker</groupId>
                <artifactId>freemarker</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
    View Code

    编写UserServiceImpl

    @Service
    public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
        @Override
        public User findByName(String username) {
            return baseMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getUsername, username));
        }
    }

    Realm

    public class ShiroRealm extends AuthorizingRealm {
    
        @Autowired
        private IUserService userServiceImpl;
        /**
         * 认证
         * @param authenticationToken
         * @return
         * @throws AuthenticationException
         */
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
            String principal = (String) authenticationToken.getPrincipal();
            User user = userServiceImpl.findByName(principal);
            if(user!=null){
                return new SimpleAuthenticationInfo(user.getUsername(),user.getPassword(),this.getName());
            }
            return null;
        }
        /**
         * 授权
         * @param principalCollection
         * @return
         */
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
            return null;
        }
    }

    ShiroRealm没有被标记为spring容器管理的bean,为什么可以@AutoWired属性注入呢?

    原因是在ShiroConfig中,shiroRealm被Spring容器管理

    @Configuration
    public class ShiroConfig {
        //ShiroFilterFactoryBean(过滤器工厂对象:初始化SecurityManager、请求处理)
        @Bean
        public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
            ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
            // 设置 securityManager
            shiroFilterFactoryBean.setSecurityManager(securityManager);
    
            LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
    
            filterChainDefinitionMap.put("/login", "anon");
            // 所有请求都要认证
            filterChainDefinitionMap.put("/**", "authc");
    
            shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
    
            //指定登录页面
            shiroFilterFactoryBean.setLoginUrl("/tologin");
    
            return shiroFilterFactoryBean;
        }
        //DefaultWebSecurityManager(对应SecurityManager对象)
        @Bean
        public SecurityManager securityManager() {
            DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
            // 配置 SecurityManager,并注入 shiroRealm
            securityManager.setRealm(shiroRealm());
            return securityManager;
        }
    
        //Realm 需要自定义
        @Bean
        public ShiroRealm shiroRealm() {
            // 配置 Realm
            return new ShiroRealm();
        }
    }
    View Code

    加密

    在数据准备时密码是经过加密处理的,但是登录请求的密码是明文,密码通过equals方法继续比较的,所以比较之前需要把明文密码进行加密处理

    shiro中密码比较默认匹配器是equals

    在AuthenticatingRealm中的assertCredentialsMatch

    可以看到getCredentialsMatcher方法获取匹配器,那么就可以设置匹配器不使用其默认匹配器。

    在shiro的配置类中的Realm对象设置匹配器

        //Realm 需要自定义
        @Bean
        public ShiroRealm shiroRealm() {
            // 配置 Realm
            ShiroRealm shiroRealm = new ShiroRealm();
    
            //修改密码匹配器
            HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
            hashedCredentialsMatcher.setHashAlgorithmName("MD5");
            shiroRealm.setCredentialsMatcher(hashedCredentialsMatcher);
            return shiroRealm;
        }
  • 相关阅读:
    Swift
    UIWindow 详解及使用场景
    点击状态栏回到顶部的功能失效的解决办法
    iOS
    从经典问题来看 Copy 方法
    从汇编层面深度剖析C++虚函数
    数值的整数次方
    求整数二进制中1的个数
    C++中的位运算总结
    嵌入在C++程序中的extern "C"
  • 原文地址:https://www.cnblogs.com/WarBlog/p/15176704.html
Copyright © 2011-2022 走看看