SpringBoot整合Shiro实现账号密码登录

shiro安全框架简介

Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。

三个核心组件:Subject, SecurityManager 和 Realms.

  • Subject:代表了当前用户的安全操作,SecurityManager则管理所有用户的安全操作。
  • SecurityManager:它是Shiro框架的核心,Shiro通过SecurityManager来管理内部组件实例,并通过它来提供安全管理的各种服务。
  • Realm: Realm充当了Shiro与应用安全数据间的“桥梁”或者“连接器”。当对用户执行认证(登录)和授权(访问控制)验证时,Shiro会从应用配置的Realm中查找用户及其权限信息。Realm实质上是一个安全相关的DAO:它封装了数据源的连接细节,并在需要时将相关数据提供给Shiro。当配置Shiro时,你必须至少指定一个Realm,用于认证和(或)授权。
  • 导入依赖(pom.xml) 

        <!--整合Shiro安全框架-->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.4.0</version>
        </dependency>
        <!--集成jwt实现token认证-->
        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.2.0</version>
        </dependency>
  • 创建 ShiroConfig 配置类

@Configuration
public class ShiroConfig {

    /**
     * ShiroFilterFactoryBean
     */
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager) {
        ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
        //设置安全管理器
        factoryBean.setSecurityManager(defaultWebSecurityManager);
        // 添加shiro的内置过滤器
        /*
         *  anon:无需认证就可以访问
         *  authc:必须认证才能访问
         *  user:必须拥有 记住我 功能才能用
         *  perms:拥有对某个资源的权限能访问
         *  role:拥有某个角色权限能访问
         */
        Map<String, String> filterMap = new LinkedHashMap<>();
        // 放行不需要权限认证的接口
        //放行登录接口
        filterMap.put("/login/**", "anon");
        //放行用户接口
        filterMap.put("/", "anon");             // 网站首页
  
        //认证管理员接口
        filterMap.put("/administrators/**", "authc");
        factoryBean.setFilterChainDefinitionMap(filterMap);
        // 设置无权限时跳转的 url
        // 设置登录的请求
        factoryBean.setLoginUrl("/login/toLogin");

        return factoryBean;
    }

    /**
     * 注入 DefaultWebSecurityManager
     */
    @Bean(name = "securityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("customRealm") CustomRealm customRealm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //关联CustomRealm
        securityManager.setRealm(customRealm);
        return securityManager;
    }

    /**
     * 注入 securityManager
     */
    @Bean
    public CustomRealm customRealm() {
        return new CustomRealm();
    }

}
  • 创建密码登录时验证授权 CustomRealm 类

@Component
public class CustomRealm extends AuthorizingRealm {

    @Autowired
    AdministratorsService administratorsService;

    /*
     * 设置加密方式
     */
    {
        HashedCredentialsMatcher mather = new HashedCredentialsMatcher();
        // 加密方式
        mather.setHashAlgorithmName("md5");
        // 密码进行一次运算
        mather.setHashIterations(512);
        this.setCredentialsMatcher(mather);
    }

    /**
     * 授权
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        System.out.println("————授权————doGetAuthorizationInfo————");

        return null;
    }

    /**
     * 认证
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("————认证————doGetAuthenticationInfo————");

        UsernamePasswordToken userToken = (UsernamePasswordToken) token;
        // 连接数据库  查询用户数据
        QueryWrapper<Administrators> wrapper = new QueryWrapper<>();
        wrapper.eq("username", userToken.getUsername());
        Administrators administrators = administratorsService.getOne(wrapper);

        if (administrators == null) {
            return null;  // 抛出异常 UnknownAccountException
        }
        // 密码认证,shiro做
        return new SimpleAuthenticationInfo("", administrators.getPassword(), "");
    }

}
  • 控制层用户密码登录

//用户名登录
    @ApiOperation(value = "管理员登录", notes = "用户名登录--不进行拦截")
    @PostMapping("/doLogin")
    public String doLogin(@RequestParam("username") String username,
                          @RequestParam("password") String password,
                          HttpSession session,Model model) {
        // 获取当前的用户
        Subject subject = SecurityUtils.getSubject();
        // 封装用户的登录数据
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        try {
            subject.login(token);
            //保存session会话 管理员名字
            session.setAttribute("adname", username);
            return "admin";
        } catch (UnknownAccountException e) {
            model.addAttribute("usererror", "用户名错误!请重新输入。");
            return "login";
        } catch (IncorrectCredentialsException ice) {
            model.addAttribute("pwerror", "密码错误!请重新输入。");
            return "login";
        }
    }
posted @ 2021-02-26 10:36  風青宇  阅读(721)  评论(0编辑  收藏  举报