Springboot+shiro основан на аутентификации URL и аутентификации авторизации.

Shiro

Широ некоторое время наблюдает. Но поскольку я не понимал эту часть раньше, особого прогресса в изучении этого не было. Тем не менее, очень важно понимать, что управление разрешениями очень важно в повседневной разработке, поэтому вы должны стиснуть зубы.Функция реализации:

  • Аутентификация
  • Авторизация URL для разных страниц
  • Решение для входа в систему за несколькими столами
  • Множественный доступ к одной и той же странице

Завершенный проект на github, приветственная звезда

Springboot полный адрес интеграции с обучением

Четыре компонента сиро:

  • Аутентификация — подтверждение личности пользователя, обычно называемое логином.
  • Авторизация - Контроль доступа
  • Криптография - защитить или скрыть данные
  • Управление сеансом Состояние, зависящее от времени, для каждого пользователя

Широ имеет встроенные фильтры, которые могут реализовывать перехватчики, связанные с разрешениями.

  • Часто используемые фильтры:

  • anon: 无需认证(登录)可以访问

  • authc: 必须认证才可以访问

  • user: 如果使用rememberMe的功能可以直接访问

  • perm: 该资源必须得到资源权限才可以访问

  • role: 该资源必须得到角色权限才可以访问

Здесь используется только аутентификация личности и авторизация, а аутентификация разрешений используется лишь немного.Принцип shiro — это инкапсулированный фильтр, который может автоматически дополнять некоторый контент перед доступом к браузеру.

Конфигурация сиро состоит из двух основных частей:shiroconfig和自定义的Realm(继承AuthorizingRealm). Среди них shiroconfig — основной конфигурационный файл shiro, а кастомный Realm в основном переписан.AuthorizingRealmЭти два метода — проверка подлинности удостоверения и проверка подлинности авторизации для вызова сравнения запросов к базе данных. И если вам нужен ролевой доступ, вам нужно переписать фильтр.

Прелюдия

Структура проекта:

在这里插入图片描述

окружающая обстановка:

  • Springboot2
  • mybatis
  • shiro

Новая таблица:

在这里插入图片描述

Соответствующий компонент:

package com.shiro.bean;

public class student {
    private String username;
    private String password;
    private String role;
    private String perm;
   //省略get set

Простой запрос Mybatis:

package com.shiro.mapper;


import com.shiro.bean.student;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

@Mapper
public interface studentMapper {

    @Select("select  * from student where username=#{name}")
    student findByName(String name);
}

Не указывайте html и sql, подробности можно скачать с GitHub.

каталог страниц,:

Файл конфигурации ядра shiro (rolesFilter не обязателен).

UserRealm.java

package com.shiro.config;

import com.shiro.bean.student;
import com.shiro.mapper.studentMapper;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;


/**
 * 自定义Realm
 * @author bigsai
 *
 */
public class UserRealm extends AuthorizingRealm{

	@Autowired(required = false)
	private studentMapper studentMapper;
	private final Logger logger= LoggerFactory.getLogger(UserRealm.class);
	/**
	 * 执行授权逻辑
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
		logger.info("执行逻辑授权");

		//给资源进行授权
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

		//添加资源的授权字符串
		//到数据库查询当前登录用户的授权字符串
		//获取当前登录用户
		Subject subject = SecurityUtils.getSubject();
		student user = (student) subject.getPrincipal();
		student dbUser = studentMapper.findByName(user.getUsername());

		info.addRole(user.getRole());//添加role 和perms  role代表角色 perms代表操作,或者动作等。用于颗粒化权限管理
		info.addStringPermission(dbUser.getPerm());
		System.out.println("user:"+dbUser.getPerm());
		return info;
	}
	/**
	 * 执行认证逻辑
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0) throws AuthenticationException {
		System.out.println("执行认证逻辑");
		//编写shiro判断逻辑,判断用户名和密码
		//1.判断用户名
		UsernamePasswordToken token = (UsernamePasswordToken)arg0;

		student user = studentMapper.findByName(token.getUsername());

		if(user==null){
			//用户名不存在
			return null;//shiro底层会抛出UnKnowAccountException
		}

		//2.判断密码
		return new SimpleAuthenticationInfo(user,user.getPassword(),"");
	}

}

rolesFilter

package com.shiro.config;

import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authz.AuthorizationFilter;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

// AuthorizationFilter抽象类事项了javax.servlet.Filter接口,它是个过滤器。
public class rolesFilter extends AuthorizationFilter {

    @Override
    protected boolean isAccessAllowed(ServletRequest req, ServletResponse resp, Object mappedValue) throws Exception {
        Subject subject = getSubject(req, resp);
        String[] rolesArray = (String[]) mappedValue;

        if (rolesArray == null || rolesArray.length == 0) { //没有角色限制,有权限访问
            return true;
        }
        for (int i = 0; i < rolesArray.length; i++) {
            if (subject.hasRole(rolesArray[i])) { //若当前用户是rolesArray中的任何一个,则有权限访问
                return true;
            }
        }
        return false;
    }
}

shiroConfig: основная конфигурация широ

package com.shiro.config;

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 javax.servlet.Filter;
import java.util.LinkedHashMap;
import java.util.Map;


/**
 * Shiro的配置类
 *
 * @author bigsai
 */
@Configuration
public class ShiroConfig {

    /**
     * 创建ShiroFilterFactoryBean
     */
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

        //设置安全管理器
        shiroFilterFactoryBean.setSecurityManager(securityManager);


        Map<String, Filter> filtersMap = new LinkedHashMap<>();
        filtersMap.put("rolesFilter",new rolesFilter());
        shiroFilterFactoryBean.setFilters(filtersMap);//使用自定义fitter
        //添加Shiro内置过滤器
        /**
         * Shiro内置过滤器,可以实现权限相关的拦截器
         *    常用的过滤器:
         *       anon: 无需认证(登录)可以访问
         *       authc: 必须认证才可以访问
         *       user: 如果使用rememberMe的功能可以直接访问
         *       perm: 该资源必须得到资源权限才可以访问
         *       role: 该资源必须得到角色权限才可以访问
         */
        Map<String, String> filterMap = new LinkedHashMap<String, String>();



        filterMap.put("/login", "anon");//要将登陆的接口放出来,不然没权限访问登陆的接口
        filterMap.put("/getcontroller", "anon");
//
        //授权过滤器
        //注意:当前授权拦截后,shiro会自动跳转到未授权页面
        filterMap.put("/add", "perms[add]");
        filterMap.put("/update", "perms[update]");

//
        filterMap.put("/test1.html","rolesFilter[admin,user]");
        filterMap.put("/*", "authc");//authc即为认证登陆后即可访问

        
        //修改调整的登录页面
        shiroFilterFactoryBean.setLoginUrl("/index");
        //设置未授权提示页面
        shiroFilterFactoryBean.setUnauthorizedUrl("/noAuth");

        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);


        return shiroFilterFactoryBean;
    }

    /**
     * 创建DefaultWebSecurityManager
     */
    @Bean(name = "securityManager")
    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();
    }

}

Аутентификация

Аутентификация личности — это проверка входа. Это первый уровень фильтрации, и когда пользователь не вошел в систему, он возвращается к интерфейсу, который не вошел в систему. В контроллере ядро ​​входа в систему:

 @RequestMapping("/login")
    public String login(String name, String password, Model model, HttpServletRequest request) {

        model.addAttribute("nama", "给个star");
        /**
         * 使用Shiro编写认证操作
         */
        //1.获取Subject
        Subject subject = SecurityUtils.getSubject();

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

        //3.执行登录方法
        try {
            subject.login(token);

            //登录成功
            //跳转
            return "redirect:/index2";
        } catch (UnknownAccountException e) {
            //e.printStackTrace();
            //登录失败:用户名不存在
            model.addAttribute("msg", "用户名不存在");
            return "login";
        } catch (IncorrectCredentialsException e) {
            //e.printStackTrace();
            //登录失败:密码错误
            model.addAttribute("msg", "密码错误");
            return "login";
        }
    }

в выпуске

	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0) throws AuthenticationException {
		System.out.println("执行认证逻辑");
		//编写shiro判断逻辑,判断用户名和密码
		//1.判断用户名
		UsernamePasswordToken token = (UsernamePasswordToken)arg0;

		student user = studentMapper.findByName(token.getUsername());
		if(user==null){
			//用户名不存在
			return null;//shiro底层会抛出UnKnowAccountException
		}
		//2.判断密码
		return new SimpleAuthenticationInfo(user,user.getPassword(),"");
	}

И это только обработка внешнего вида, а в выпуске (наследованиеAuthorizingRealm) требует гиперемииdoGetAuthenticationInfo()метод.

Общий процесс таков:登录——>拿账号密码检验———>用着token的账号通过你的sql查询对象——>比对数据是否一致——>通过还是抛各种异常

А в shiroConfig при фильтрации по urlauthcполучить доступ

Как работает многотабличный источник входа?

Могут возникнуть следующие ситуации: сторона учителя и сторона ученика исходят из двух таблиц и двух интерфейсов входа в систему Как я могу использовать аутентификацию shiro. Для такого рода проблем можно настроить несколько релизов, но я думаю, если это просто, то можно передать параметр под разными интерфейсами входа, и этот параметр передается сеансом. потому что,shiro的session和网页httprequest获得的session是同一个session.

Таким образом, когда вы передаете атрибут для освобождения при входе в систему, вы можете использовать if else для оценки, а затем выполнять разные методы запроса на разных интерфейсах входа.

Управление авторизацией

связан с процессом是否登录——>是/否-- (Да) -->查询role/perm添加到subject——>过滤器校验该url需要权限——>可以访问/权限不足

Основным URL-адресом широ можно управлять в соответствии с ролями (role) и ресурсами (perm). Для роли это может быть администратор, учитель и т.д., а для пермь это может быть действие, операция и т.д. == и, возможно, роль имеет несколько ролей и perm==. Точно так же авторизация заключается в запросе роли или поля perm базы данных и добавлении ее в роль. Конечно, конкретный API не вводится. Основной метод описан выше:

protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
		logger.info("执行逻辑授权");

		//给资源进行授权
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

		//添加资源的授权字符串
		//到数据库查询当前登录用户的授权字符串
		//获取当前登录用户
		Subject subject = SecurityUtils.getSubject();
		student user = (student) subject.getPrincipal();
		student dbUser = studentMapper.findByName(user.getUsername());

		info.addRole(user.getRole());//添加role 和perms  role代表角色 perms代表操作,或者动作等。用于颗粒化权限管理
		info.addStringPermission(dbUser.getPerm());
		System.out.println("user:"+dbUser.getPerm());
		return info;
	}

А также в URL

 filterMap.put("/add", "perms[add]");
 filterMap.put("/update", "roles[admin]");

Как исправить проблемы с несколькими ролями/ресурсами пользовательского интерфейса

Часто встречается такая ситуация: к интерфейсу/странице могут обращаться две и более ролей. Тогда конфигурация фонового фильтра является полной. Конфигурация сиро по умолчанию — и вместо или. Это требует, чтобы мы определили наше собственное наследование фильтраAuthorizationFilterОт написания соответствующего метода.

Возьмем в качестве примера многоролевой доступ. Из написанного выше находится файл rolesFilter. При его использовании вы должны сначала объявить фильтр, прежде чем его можно будет использовать.

在这里插入图片描述

эффект доступа

Авторизован на странице

Выполнить тест: доступ к другим интерфейсам возвращается к этому интерфейсу

在这里插入图片描述
在这里插入图片描述

После успешного входа в систему можно получить доступ к интерфейсу

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
Есть небольшое примечание: если версия mybatis 2.0 конфликтует с spring-start-web. У меня нет проблем с версией 1.3.2.

Адрес проекта на гитхабе

Springboot полный адрес интеграции с обучением