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;
    }

 

posted @ 2021-08-24 13:09  一杯水M  阅读(67)  评论(0编辑  收藏  举报