SpringBoot整合Shiro

(1)Shiro介绍

Shiro简介:Shiro是一个强大的简单易用的Java安全框架,主要用来更便捷的认证,授权,加密,会话管理。Shiro首要的和最重要的目标就是容易使用并且容易理解,通过Shiro易于理解的API,您可以快速、轻松地获得任何应用程序——从最小的移动应用程序最大的网络和企业应用程序。

Shiro的架构有三个主要概念:SubjectSecurityManager 和 Realms

Subject: 当前参与应用安全部分的主角。可以是用户,可以试第三方服务,可以是cron 任务,或者任何东西。主要指一个正在与当前软件交互的东西。所有Subject都需要SecurityManager,当你与Subject进行交互,这些交互行为实际上被转换为与SecurityManager的交互。

SecurityManager:安全管理员,Shiro架构的核心,它就像Shiro内部所有原件的保护伞。然而一旦配置了SecurityManager,SecurityManager就用到的比较少,开发者大部分时间都花在Subject上面。当你与Subject进行交互的时候,实际上是SecurityManager在背后帮你举起Subject来做一些安全操作。

Realms: Realms作为Shiro和你的应用的连接桥,当需要与安全数据交互的时候,像用户账户,或者访问控制,Shiro就从一个或多个Realms中查找。Shiro提供了一些可以直接使用的Realms,如果默认的Realms不能满足你的需求,你也可以定制自己的Realms。

(2)SpringBoot中使用Shiro

(1)环境的配置

这里连接数据库来进行账户名,密码的比对,采用mybatis框架

 <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.4.1</version>
        </dependency>
 <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.0</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
   <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.12</version>
        </dependency>


        <dependency>
            <groupId>com.github.theborakompanioni</groupId>
            <artifactId>thymeleaf-extras-shiro</artifactId>
            <version>2.0.0</version>
        </dependency>

 

 

(2)pojo实体类,service层,mapper及相关配置文件xml的编写

(1)pojo层:

这里要和数据库中的字段相对应

package com.csh.springbootshiro.pojo;


import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class User {
    private int id;
    private String username;
    private String password;
    private String perms;
}

 相对应的数据库:

 (2)mapper及配置文件

package com.csh.springbootshiro.mapper;


import com.csh.springbootshiro.pojo.User;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;

@Mapper
@Repository
public interface UserMapper {

    public User findbyname(String name);


}

 对应的xml文件:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.csh.springbootshiro.mapper.UserMapper">
    <select id="findbyname" parameterType="String" resultType="User">
        select * from person where username=#{name}
    </select>

</mapper>

 (3)service层

package com.csh.springbootshiro.service;

import com.csh.springbootshiro.pojo.User;

public interface UserService {

    public User findbyname(String name);


}

 

package com.csh.springbootshiro.service;

import com.csh.springbootshiro.mapper.UserMapper;
import com.csh.springbootshiro.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;


@Service
public class UserServiceImpl implements UserService{

    @Autowired
    UserMapper userMapper;

    @Override
    public User findbyname(String name) {
       return userMapper.findbyname(name);
    }
}

(3)视图控制层(要有账户密码错误的反馈信息)和shiro配置类的编写

ShiroConfig配置类的编写:

package com.csh.springbootshiro.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.HashMap;

@Configuration
public class ShiroConfig {
    //创建 ShiroFilterFactoryBean


    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("defaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager)
    {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

        shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
        /*
添加Shiro内置过滤器,常用的有如下过滤器:
anon: 无需认证就可以访问
authc: 必须认证才可以访问
user: 如果使用了记住我功能就可以直接访问
perms: 拥有某个资源权限才可以访问
role: 拥有某个角色权限才可以访问
*/

        HashMap<String, String> map = new HashMap<>();//这里进行的是每个url的访问权限限制
//        map.put("/user/add","authc");
//        map.put("/user/update","authc");

        map.put("/user/add","perms[user:add]");
        map.put("/user/update","perms[user:update]");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
        shiroFilterFactoryBean.setLoginUrl("/tologin");//这里是点击登录是发送一个请求来到登录界面
        shiroFilterFactoryBean.setUnauthorizedUrl("/noauth");//无权访问是发送一个请求来到指定界面
        return shiroFilterFactoryBean;
    }
   //创建 DefaultWebSecurityManage

    @Bean
    public DefaultWebSecurityManager defaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm)
    {
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
        defaultWebSecurityManager.setRealm(userRealm);
        return defaultWebSecurityManager;
    }



    // 创建 realm 对象,在建个类来继承AuthorizingRealm这个类
    @Bean
    public UserRealm userRealm()
    {
        return new UserRealm();
    }

    @Bean
    public ShiroDialect getShiroDialect(){
        return new ShiroDialect();
    }

}

 UserReaml类:

package com.csh.springbootshiro.config;

import com.csh.springbootshiro.pojo.User;
import com.csh.springbootshiro.service.UserService;
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.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;



public class UserRealm extends AuthorizingRealm {

    @Autowired
    UserService userService;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("执行了=>授权逻辑PrincipalCollection");
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        Subject subject = SecurityUtils.getSubject();//总的来说,SecurityUtils.getSubject()是每个请求创建一个Subject, 并保存到ThreadContext的resources(ThreadLocal<Map<Object, Object>>)变量中,也就是一个http请求一个subject,并绑定到当前线程
        User user = (User) subject.getPrincipal();//SecurityUtils.getSubject().getPrincipal()获取封装的用户信息
        subject.getSession().setAttribute("loginuser",user);//登录之后才会显示相关的页面资源,游客访问的话只有一个登录按钮
        simpleAuthorizationInfo.addStringPermission(user.getPerms());
        return simpleAuthorizationInfo;
    }

    @Override
    //这里是在登录界面进行的
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //AuthenticationToken authenticationToken拿到的是视图控制层传来的,UsernamePasswordToken 是用来存储用户和密码的
        System.out.println("执行了=>认证逻辑AuthenticationToken");
        UsernamePasswordToken usernamePasswordToken= (UsernamePasswordToken) authenticationToken;
        User user = userService.findbyname(usernamePasswordToken.getUsername());//在数据库中进行查找该用户
        if(user==null)
        {
            return null;//不存在该用户,返回null
        }
        else
        {
            return new SimpleAuthenticationInfo(user,user.getPassword(),"");//这里进行密码的判断,在视图控制层返回相关的信息
        }





    }
}

 controller:

package com.csh.springbootshiro.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 MyController {

    @RequestMapping({"/","/index"})
    public String index(){
        return "index";
    }

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

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

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


    @RequestMapping("/login")
    public String login(String username, String password, Model model)
    {
        //这里拿到了登录表单传来的用户名和密码
        Subject subject= SecurityUtils.getSubject();
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username, password);
        try{
            subject.login(usernamePasswordToken);//来进行信息的匹配
            return "index";//登录成功
        }catch (UnknownAccountException e)//UnknownAccountException用户不存在,返回的null
        {
            model.addAttribute("msg","用户不存在");//反馈给前端的登录界面
            return "login";
        }catch (IncorrectCredentialsException e)//IncorrectCredentialsException 密码错误
        {
            model.addAttribute("msg","用户密码错误");
            return "login";
        }
    }

    @RequestMapping("/noauth")
    @ResponseBody
    public String noauth()
    {
        return "未经许可,不可授权";
    }

}

 (3)成果展示

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jakeonil

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值