初识Shiro(小demo,很菜我知道)----------畅游csdn的第一篇文

前言
首先感谢我的好朋友-----笔名 鹏仔 引导我入坑,虽然他如今还未毕业
再次感谢我的真正入门老师 Mr Cui,是你让我认识了public static void main(String[]args){system.out.println("Hello worldl")},用一段Hello world走进了另一个世界。
其次还要感谢这段路上所有的小伙伴的帮助、调试、Ctrl+c、Ctrl+v,QQ远程,虽然目前增删改查还要再磨磨,太多业务逻辑没有锻炼,但感谢你们的代码,感谢你们的智慧。
最后感谢家人的不计回报的关心爱护,学校至社会,初来乍到,每一步都举步维艰,感谢你们的支持信任


Shiro


1、导入依赖
2、配置文件
3、需要工具:后台SpringBoot+mysql
前台:thymeleaf模板

Shrio三大核心

Subject 用户
SecurityManager 管理所有用户
Realm 连接数据
在这里插入图片描述

Demo结构
在这里插入图片描述

一、TestController中的配置
RequestMapping("/login")的跳转方法运行时,进行三步操作:
1、获取Subject当前用户
2、获取前台name,password封装成token令牌

   @RequestMapping("/login")
    public String login(String name,String password,Model model){
        //获取当前用户
        Subject subject = SecurityUtils.getSubject();
        //封装当前用户登录数据并封装成token
        UsernamePasswordToken token=  new UsernamePasswordToken(name,password);
        try{
            subject.login(token);//执行登录方法,如果没有異常就说明ok了
            return "index";
        }catch(UnknownAccountException e){//用户名異常
            model.addAttribute("msg","用户名错误");
            return "login";
        }catch (IncorrectCredentialsException e){
            model.addAttribute("msg","密码错误");
            return  "login";
        }
    }

3、执行异常捕获

  try{
            subject.login(token);//执行登录方法,如果没有異常就说明ok了
            return "index";
        }catch(UnknownAccountException e){//用户名異常
            model.addAttribute("msg","用户名错误");
            return "login";
        }catch (IncorrectCredentialsException e){
            model.addAttribute("msg","密码错误");
            return  "login";
        }

(1)、try凭借token令牌进入UserRealm类中进行认证
(2)、catch(第一个)块中为token认证完毕后 前台用户名与系统内的用户名不匹配,进而使用model.addAttribute进行存储错误信息,前台展示,并返回到登陆页面
(3)、catch(第二个)块中为token认证完毕,密码不一致时返回的状态,同样返回到登录页面
//controller完整代码

package com.sh.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.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class TestController {

    @RequestMapping({"/", "/index"})
    public String tologin(Model model) {
        model.addAttribute("mes", "Hello shiro");
        return "index";
    }

    @RequestMapping("/user/add")
    public String add() {
        return "user/add";
    }

    @RequestMapping("user/updata")
    public String updata() {
        return "user/updata";
    }

    @RequestMapping("/toLogin")
    public String toLogin(){
    return "login";
    }


    @RequestMapping("/login")
    public String login(String name,String password,Model model){
        //获取当前用户
        Subject subject = SecurityUtils.getSubject();
        //封装当前用户登录数据并封装成token
        UsernamePasswordToken token=  new UsernamePasswordToken(name,password);
        try{
            subject.login(token);//执行登录方法,如果没有異常就说明ok了
            return "index";
        }catch(UnknownAccountException e){//用户名異常
            model.addAttribute("msg","用户名错误");
            return "login";
        }catch (IncorrectCredentialsException e){
            model.addAttribute("msg","密码错误");
            return  "login";
        }
    }

    @RequestMapping("/noauth")
    @ResponseBody
    public String noshouquan(){
        return "未经授权不得访问此页面";
    }

}

二、ShiroConfig中的配置
注:该类为shiro的全局配置类,下文中UserRealm作为数据连接器会将前台数据传入进行处理,每一步的执行操作在注释上已用数字标识了顺序。
1、创建realm对象(也就是下文中的UserRealm)

//创建Realm对象(1)
    @Bean
    public UserRealm UserRealm() {
        return new UserRealm();
    }

2、设置SecurityManager,通过创建DefaultWebSecurityManager 对象关联Realm

//DefaultWebSecurityManager(2)
    @Bean(name = "securityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("UserRealm") UserRealm userRealm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //关联realm
        securityManager.setRealm(userRealm);
        return securityManager;
    }

3、
(1)、设置安全管理器
(2)、通过创建Map存放需要
a、拦截的页面
b、访问权限的路径以及权限标识
(3)、//设置登录请求的权限
bean.setFilterChainDefinitionMap(filterMap);
//设置登录的请求
bean.setLoginUrl("/toLogin");
//设置未授权页面
bean.setUnauthorizedUrl("/noauth");
//shiroFilterFactoryBean(3)

   @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager) {
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        //设置安全管理器
        bean.setSecurityManager(defaultWebSecurityManager);
        //添加shiro的内置过滤器
        /*
        anno:无需认证就可以访问
        authc:必须认证了才能访问
        perms:拥有对某个资源的权限才能访问
        role:拥有某个角色权限才能访问
         */
        Map<String, String> filterMap = new LinkedHashMap<>();
        //授权 正常情况会跳到未授权页面
        filterMap.put("/user/add", "perms[user:add]");
        filterMap.put("/user/updata", "perms[user:updata]");
        //设置登录请求的权限
        bean.setFilterChainDefinitionMap(filterMap);
        //拦截
        filterMap.put("/user/*", "authc");
        //设置登录的请求
        bean.setLoginUrl("/toLogin");
        //设置未授权页面
        bean.setUnauthorizedUrl("/noauth");
        return bean;
    }

//ShiroConfig 完整代码

package com.sh.config;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
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.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {
    //shiroFilterFactoryBean(3)
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager) {
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        //设置安全管理器
        bean.setSecurityManager(defaultWebSecurityManager);
        //添加shiro的内置过滤器
        /*
        anno:无需认证就可以访问
        authc:必须认证了才能访问
        perms:拥有对某个资源的权限才能访问
        role:拥有某个角色权限才能访问
         */
        Map<String, String> filterMap = new LinkedHashMap<>();
        //授权 正常情况会跳到未授权页面
        filterMap.put("/user/add", "perms[user:add]");
        filterMap.put("/user/updata", "perms[user:updata]");
        //设置登录请求的权限
        bean.setFilterChainDefinitionMap(filterMap);
        //拦截
        filterMap.put("/user/*", "authc");
        //设置登录的请求
        bean.setLoginUrl("/toLogin");
        //设置未授权页面
        bean.setUnauthorizedUrl("/noauth");
        return bean;
    }

    //DefaultWebSecurityManager(2@Bean(name = "securityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("UserRealm") UserRealm userRealm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //关联realm
        securityManager.setRealm(userRealm);
        return securityManager;
    }

    //创建Realm对象(1)
    @Bean
    public UserRealm UserRealm() {
        return new UserRealm();
    }

    //整合ShiroDialect:用来整合Shiro thymeleaf
    @Bean
    public ShiroDialect getShiroDialect() {
        return new ShiroDialect();
    }


}

三、UserRealm中的配置(用以连接用户数据)
1、该类需要继承AuthorizingRealm 父类,初学shiro只重写了两个方法(doGetAuthorizationInfo+doGetAuthenticationInfo)这两个方法的名称非常容易搞混,这两个方法的作用却大相径庭,但功能非常重要,doGetAuthorizationInfo为授权,doGetAuthenticationInfo为认证。前文中token令牌需要认证的地方就是此类的doGetAuthenticationInfo处。
2、doGetAuthenticationInfo(认证)

//认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("执行了=》认证doGetAuthenticationInfo");
        //连接真实数据库
        UsernamePasswordToken userToken = (UsernamePasswordToken) authenticationToken;
        UserPojo user = service.querUserByName(userToken.getUsername());
        if (user == null) {//没有该用户名
            return null;
        }
        //把当前登录用户存入session
        Subject currentsubject = SecurityUtils.getSubject();
        Session session = currentsubject.getSession();
        session.setAttribute("loginuser",user);
        //判断密码是否一直
        return new SimpleAuthenticationInfo(user, user.getPassword(), "");
    }
}

(1)、 此方法接受的参数为前文中的token令牌,通过此令牌实例化对象UserToken,进而通过调用前台name传至后台查询出相应的User实体数据并封装。
(2)、判断用户名:if判断如果查无此数据,直接Return null,此时该方法会捕获异常,并在上文的Controller中进行model存储异常信息处理
(3)、判断密码:在return new SimpleAuthenticationInfo(user, user.getPassword(), “”)中,shiro就可以进行密码判断,判断完毕如果密码不一致自动抛出异常,controller处理同上。
(4)、通过session全局作用域存储当前用户,为后续的首页登录按钮做铺垫
注:通过此上几步,完成了基本的Shiro的用户名与密码的认证
3、doGetAuthorizationInfo(授权)
(1)、创建SimpleAuthorizationInfo 对象
(2)、获取当前用户(此时的用户通过subject.getPrincipal()获取的为认证方法传递过来的用户)
(3)、通过 info.addStringPermission(user.getPerm()),shiro进行权限认证,此权限设置在权限管理器。

 //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("执行了=》授权doGetAuthorizationInfo");
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //获取当前登录用户,该用户从认证里传递而来
        Subject subject = SecurityUtils.getSubject();
        UserPojo user = (UserPojo)subject.getPrincipal();
        //设置权限认证
        info.addStringPermission(user.getPerm());
        System.out.println(user.getPerm());
        return info;
    }

//UserRealm完整代码

package com.sh.config;
import com.sh.Service.UserService;
import com.sh.pojo.UserPojo;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;

//自定义的UserRealm    继承AuthorizingRealm
public class UserRealm extends AuthorizingRealm {
    @Autowired
    UserService service;

    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("执行了=》授权doGetAuthorizationInfo");
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //获取当前登录用户,该用户从认证里传递而来
        Subject subject = SecurityUtils.getSubject();
        UserPojo user = (UserPojo)subject.getPrincipal();
        //设置权限认证
        info.addStringPermission(user.getPerm());
        System.out.println(user.getPerm());
        return info;
    }

    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("执行了=》认证doGetAuthenticationInfo");
        //连接真实数据库
        UsernamePasswordToken userToken = (UsernamePasswordToken) authenticationToken;
        UserPojo user = service.querUserByName(userToken.getUsername());
        if (user == null) {//没有该用户名
            return null;
        }
        //把当前登录用户存入session
        Subject currentsubject = SecurityUtils.getSubject();
        Session session = currentsubject.getSession();
        session.setAttribute("loginuser",user);
        return new SimpleAuthenticationInfo(user, user.getPassword(), "");
    }
}

上述为我学习shiro最基本的操作与理解,也是我的第一篇csdn文,仅此记录、总结我现阶段对shiro的理解,具体学习请前往https://www.bilibili.com/video/BV1PE411i7CV?p=38

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值