shiro springboot 认证

2020-08-25  本文已影响0人  杨健kimyeung
  1. 导入相关依赖

  2. 配置shiro

    2.1 配置类
    2.2 登录页配置
    2.3 shiro默认过滤器

  3. 自定义Reaml类

  4. 用户登录
    3.1 页面设计
    3.2 登录处理
    3.3 密码匹配原理

1、导入依赖

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

2、配置shiro

starter已经做了很多自动配置工作,具体可以参考ShiroAutoConfiguration.java、ShiroBeanAutoConfiguration.java和ShiroWebAutoConfiguration.java这几个文件

@Configuration
public class ShiroConfig {
    /**
     * 1. 注册自定义Realm
     */
    @Bean
    public UserRealm realm() {
        return new UserRealm();
    }
    /**
     * 2. 配置url过滤器
     * 统一做鉴权,即判断哪些请求路径需要用户登录,哪些请求路径不需要用户登录。
     * 只做鉴权,不做权限控制,因为权限用注解来实现。
     *
     * @return
     */
    @Bean
    public ShiroFilterChainDefinition shiroFilterChainDefinition() {
        DefaultShiroFilterChainDefinition shiroFilterChainDefinition = new DefaultShiroFilterChainDefinition();
        //不需要认证就能访问
        shiroFilterChainDefinition.addPathDefinition("/test/**", "anon");
        shiroFilterChainDefinition.addPathDefinition("/login", "anon");
        shiroFilterChainDefinition.addPathDefinition("/register", "anon");
        shiroFilterChainDefinition.addPathDefinition("/druid/**", "anon");
        //需要认证才能访问的
        shiroFilterChainDefinition.addPathDefinition("/admin/**", "authc");
        shiroFilterChainDefinition.addPathDefinition("/user/**", "authc");
        shiroFilterChainDefinition.addPathDefinition("/api/**", "authc");
        shiroFilterChainDefinition.addPathDefinition("/**", "authc");
        return shiroFilterChainDefinition;
    }
  
    /**
     * 3 配置security并设置Realm,避免required a bean named 'authorizer' that could not be found.的报错
     * @param realm
     * @return
     */
    @Bean
    public DefaultWebSecurityManager securityManager(UserRealm realm) {
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
        defaultWebSecurityManager.setRealm(realm);
        return defaultWebSecurityManager;
    }

3、自定义Realm

public class UserRealm extends AuthorizingRealm {
    @Resource
    UserService userService;
        
    /**
     * 认证
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
       //第一步:从token中取出用户名,这个用户名是用户在页面输入的信息,传递给token
        String username = (String) authenticationToken.getPrincipal();
       // 第二步通过用户名从数据库中查询出用户信息
        User user = userService.findUserByName(username);
       //  第三步 判断
        if (user == null) {
            throw new UnknownAccountException("账号不存在");
        }
        if (user.getStatus() == 0) {
            throw new LockedAccountException("账号被锁定!请与管理员联系");
        }
                // 第四步 实例化 SimpleAuthenticationInfo
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
                user, user.getPassword(), getName()
        );
        return authenticationInfo;
    }
    /**
     * 授权
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        return null;
    }
}

SimpleAuthenticationInfo 参数说明

参数 说明 备注
principal 从数据库中查询的user对象,也可以user对象的用户名。传入的一般都是user对象。 必要
hashedCredentials 传的是从数据库中获取的password,然后再与token中的password进行对比,匹配上了就通过,匹配不上就报异常。 必要
credentialsSalt 加密盐–用于加密密码对比,为了防止两用户的初始密码是一样的, 非必要
realmName 从authenticationToken中获取的用户名 必要

3、登录

在控制层的登录方法中,

创建一个usernamePasswordToken令牌,交由Shiro并调用login()方法进行登录,

如果不抛出任何异常表明登录成功,

如果抛出异常,根据异常种类返回提示出错信息

@RestController
public class LoginController {
    @PostMapping("login")
    public String login(String username, String password) {
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username, password);
        try {
            SecurityUtils.getSubject().login(usernamePasswordToken);
        } catch (IncorrectCredentialsException e) {
            throw new CustomShiroException("账号或密码错误");
        } catch (ExcessiveAttemptsException e) {
            throw new CustomShiroException("操作过于频繁,请稍后在试!");
        }
        return "success";
    }
}
上一篇 下一篇

猜你喜欢

热点阅读