springboot整合shiro

springboot整合shiro

1 shiro是什么?

Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。使用Shiro的易于理解的API,您可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。

我把它理解为做登录和页面拦截的东东。

它有三个核心组件:Subject, SecurityManager 和 Realms.
1 Subject
  可以理解为当前用户,我认为它不应该仅仅指人,而应该理解为当前的安全操作者。比如通过subject去验证登录等等。(shiro做实现,不需要我们编写)
2 SecurityManager
  它的作用是管理所有用户的安全操作。(shiro做实现,不需要我们编写)
3 Realms
它是shiro与安全数据之间的桥梁,或者连接器。当用户需要进行登录或者授权时,在它里面进行操作。说的简单点,就是在它的方法里面进行调service方法获取数据库数据。验证用户名和密码等信息。(需要我们编写)

2 好了,接下来开始说正经的了,让我们看看怎么编写以及使用的吧。。

首先,在src下建个包名为shiro,在shiro包下创建类ShiroConfig.java。在该类中写入以下内容。


package com.chenjunan.shiro; //此处别照抄

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;

/**
 * shiro配置类
 */
@Configuration
public class ShiroConfig {


  /**
         * 此方法用于创建ShiroFilterFactoryBean,该bean设置每个界面的访问权限
    *   和设置跳转的登录页面 
    *    内置多个filter 每种filter有不同权限
         */
    @Bean
    public ShiroFilterFactoryBean gethiroFilterFactoryBean(@Qualifier("defaultWebSecurityManager")
                                                                   DefaultWebSecurityManager securityManager){

        ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();

        factoryBean.setSecurityManager(securityManager);

        factoryBean.setLoginUrl("login");

        Map filterMap = new LinkedHashMap<>();
        filterMap.put("/add","authc");
        filterMap.put("/update","authc");
        filterMap.put("/login.action","anon");
       factoryBean.setFilterChainDefinitionMap(filterMap);
        return factoryBean;
    }

  //获取DefaultWebSecurityManager
    @Bean(name = "defaultWebSecurityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){

        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();

        //关联realm
        securityManager.setRealm(userRealm);

        return securityManager;
    }
    //获取自定义的realm
    @Bean(name = "userRealm")
    public UserRealm getRealm(){
        return new UserRealm();
    }
}

注: @Qualifier("userRealm") 用于通过bean的name注入指定bean

在shiro包下创建自定义的realm,我这里写UserRealm做示例。

参考代码:

package com.chenjunan.shiro;

import com.chenjunan.controller.service.UserService;
import com.chenjunan.pojo.User;
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;

/**
 * 自定义的realm
 */
public class UserRealm extends AuthorizingRealm {

    @Autowired
    private UserService userService;

    /**
     * 执行授权逻辑
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("执行授权逻辑");
        return null;
    }

    /**
     * 执行认证逻辑
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo  doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("执行授权逻辑");

        UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) authenticationToken;

        User user = userService.findByName(usernamePasswordToken.getUsername());

        if(user == null)
            return null;    //返回为null shiro会抛出 UnknownAccountException

        return new SimpleAuthenticationInfo("",user.getUser_pwd(),"");
    }
}

自定义的realm需要继承AuthorizingRealm类 重载抽象方法doGetAuthorizationInfo。通过参数不同一个执行授权逻辑,一个执行认证逻辑,本次只做认证逻辑。
UsernamePasswordToken类封装表单提交的用户名和密码。
通过注入userService从数据库获取真实用户信息。dao我这里使用的mybatis框架访问的数据库.此处不做细说。
如果通过用户名从数据库未查询到数据。则返回null,shiro会抛出UnknownAccountException异常,我们在相应controller的handler中进行捕获,做出相应。
SimpleAuthenticationInfo对象用于验证密码是都正确。我们不自己判断的原因是一般数据库不明文存放密码数据,而是存放加密后的数据。一般加密不可逆。所以将数据库加密密码和用户提供的明文数据交给SimpleAuthenticationInfo对象去判断。如果密码不相匹配,抛出IncorrectCredentialsException异常,我们在controller的handler中捕获,进行响应。

controller代码如下:

package com.chenjunan.controller;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
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;

@Controller
public class HelloController {

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

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

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

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

    @RequestMapping("/login.action")
    public String checklogin(String name, String password, Model model){


        //使用shiro编写认证操作
        //1.获取subject
        Subject subject = SecurityUtils.getSubject();

        //2.封装用户数据
        UsernamePasswordToken token = new UsernamePasswordToken(name,password);

        //3.执行登录方法
        try {
            subject.login(token);     //shiro会调用realm中的认证方法
        }catch (UnknownAccountException e){
            //用户名不存在异常
            model.addAttribute("message","用户名不存在!");
            return "error";

        }catch (IncorrectCredentialsException e){
            //密码错误
            model.addAttribute("message","密码错误!");
            return "error";
        }

        return "index";
    }

}

注:应注意的是 subject.login(token); 这句代码,shiro底层会调用UserRealm的认证逻辑方法。去进行数据库验证。
如果用户通过验证,可穿过需要验证才能访问的页面。
如果用户已经登录,shiro会在缓存中存放相关数据。

整个项目路径截图:
spring-shiro.png

个人觉得这篇博客关于shiro讲的很好,推荐!快速到达!

注:如有错误,请指正!感谢!

你可能感兴趣的:(springboot整合shiro)