Shiro学习一(基于springboot的简单登录)

4 篇文章 0 订阅

基于springboot的简单登录
首先我们需要使用IDEA设计一个springboot项目,然后引入相关的依赖。然后在项目的resource/templates下面创建出一个登录页,也就是项目的首页,运行起来以后,应该可以看到下面的景象
在这里插入图片描述之后,我们就要进行shiro相关的操作,首先需要创建一个类,是我们自定义的一个Realm,主要完成相关的认证和授权逻辑,它需要继承shiro官方提供的AuthorizingRealml类,并实现其中的两个方法

package com.example.lclepro.Config;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

public class LcleRealm extends AuthorizingRealm {

    //执行授权逻辑
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        return null;
    }

    //执行认证逻辑
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        return null;
    }
}

之后,我们需要创建一个Shiro的核心配置类,那就是SHiroConfig,他需要实现三个方法,分别实现,对于拦截器工厂,安全管理器,自定义Realm的加载代码如下

package com.example.lclepro.Config;


import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ShiroConfig {


    //实现拦截器
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("defaultWebSecurityManager") DefaultWebSecurityManager securityManager){
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        return shiroFilterFactoryBean;
    }

    //实现web安全管理器的加载
    @Bean
    public DefaultWebSecurityManager defaultWebSecurityManager(@Qualifier("lcleRealm") LcleRealm realm){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(realm);
        return securityManager;

    }

    //实现Realm的加载
    @Bean
    public LcleRealm lcleRealm(){
        return new LcleRealm();
    }
}

之后,我们介绍shiro中的第一个对象Subject,这个对象有对应的登入登出方法,而且相应的授权方法也是基于这个对象来进行的,下面先介绍shiro的相关认证过滤器

  1. anon:无需认证,任何都可以使用
  2. authc:必须认证才可以访问(即必须登录)
  3. perms:需要相关授权
  4. role:相应的角色

我们需要进行相应的操作,是的shiro能够完成url的拦截,这时候,我们在ShiroConfig类的拦截器工厂方法中添加代码段,使得shiro可以拦截请求,并直接放行首页访问请求和登陆验证请求,方便以后的测试

package com.example.lclepro.Config;


import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {


    //实现拦截器
    //@Bean注解注释在方法上,将返回的实体类交给容器处理,id是方法名
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("defaultWebSecurityManager") DefaultWebSecurityManager securityManager){
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        //设置拦截成功以后,访问的页面
        shiroFilterFactoryBean.setLoginUrl("/");
        //拦截器Map的创建
        Map<String, String> map = new HashMap<String, String>();
        //针对不同的url,使用不同的拦截器,放到map中,即可生效,完成拦截
        //拦截所有请求
        map.put("/*", "authc");
        //放行登陆请求
        map.put("/", "anon");
        //放行登录认证请求
        map.put("/user/login", "anon");
        //设置相关的map集合,完成拦截功能的收集
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
        return shiroFilterFactoryBean;
    }

    //实现web安全管理器的加载
    @Bean
    public DefaultWebSecurityManager defaultWebSecurityManager(@Qualifier("lcleRealm") LcleRealm realm){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(realm);
        return securityManager;

    }

    //实现Realm的加载
    @Bean
    public LcleRealm lcleRealm(){
        return new LcleRealm();
    }
}

这样一来,就能实现拦截,然后普先建立一个controller用来接收登陆页面拿到的用户名和密码,然后就要开始验证方法了

package com.example.lclepro.Controller;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

@Controller
@RequestMapping("user")
public class UserController {

    @PostMapping("/login")
    public ModelAndView login(@RequestParam("username") String username, @RequestParam("password") String password){
        ModelAndView mv = new ModelAndView();
        //获取到Subject对象
        Subject suject = SecurityUtils.getSubject();
        //将收集到的用户名和密码存储到token中
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        //执行登入方法
        try {
            suject.login(token);
            mv.setViewName("pages/success");
        }
        catch (UnknownAccountException e){
            //用户名不存在时抛出的异常
            mv.addObject("msg", "用户不存在,请找到合适的介绍人加入组织(๑•̀ㅂ•́)و✧");
            mv.setViewName("pages/index");
        }
        catch (IncorrectCredentialsException e){
            //用户名密码不匹配时抛出的异常
            mv.addObject("msg", "用户名与密码不匹配( ̄_, ̄ )");
            mv.setViewName("pages/index");
        }
        return mv;
    }
}

在这里,我们顺一下逻辑,当我们实例化subject对象以后,调用login方法时,就睡进入到shiro的认证逻辑代码中,即doGetAuthenticationInfo方法,传入参数类型是AuthenticationToken,我们不妨使用类型强转,转化成UsernamePasswordToken类型,获取到其中的封装过的用户名和密码,再和数据库中获取用户名和密码进行比对,完成用户登陆的逻辑

package com.example.lclepro.Config;

import com.example.lclepro.Service.UserService;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

public class LcleRealm extends AuthorizingRealm {

    @Autowired
    UserService userService;

    //执行授权逻辑
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        return null;
    }

    //执行认证逻辑,执行login()方法以后,会进入到这里,进行用户名密码的比对
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {

        //执行认证逻辑
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        //获取密码
        String password = userService.isUser(token.getUsername());
        if(password==null){
            throw new UnknownAccountException();
        }

        return new SimpleAuthenticationInfo("", password, "");
    }
}

今天的工作告一段落,简单的登录实现了,希望这场瘟疫早些过去,生活回到正轨

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值