springboot集成shiro

简介: 废话少说,先简单说下怎么用,至于shiro是什么,请移步shiro官网1、添加依赖 org.apache.

废话少说,先简单说下怎么用,至于shiro是什么,请移步shiro官网

1、添加依赖

            <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-core</artifactId>
                <version>${shiro.version}</version>
            </dependency>

            <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-web</artifactId>
                <version>${shiro.version}</version>
            </dependency>

            <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-spring</artifactId>
                <version>${shiro.version}</version>
            </dependency>

            <dependency>
                <groupId>net.mingsoft</groupId>
                <artifactId>shiro-freemarker-tags</artifactId>
                <version>${shiro-freemarker.version}</version>
            </dependency>

2、重写AuthorizingRealm

AuthorizingRealm主要包括两个方法:doGetAuthorizationInfo(PrincipalCollection principals)和doGetAuthenticationInfo(AuthenticationToken token)
1.doGetAuthenticationInfo(AuthenticationToken token)在登录认证时候被调用,即SecurityUtils.getSubject().login()执行时候被调用
2.doGetAuthorizationInfo(PrincipalCollection principals)获取权限认证信息,即SecurityUtils.getSubject().isPermitted()执行时候被调用
我这里定义成abstract 是为了提取该类为公用,其他项目可以复用集成。

public abstract class AbstarctAuthorizingRealm extends AuthorizingRealm {

    @Resource
    private IUserService userService;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        Object primaryPrincipal = principals.getPrimaryPrincipal();
        if (primaryPrincipal == null) {
            return null;
        }

        IUser user = (IUser) primaryPrincipal;

        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.setStringPermissions(findPermissions(user));
        info.setRoles(findRoles(user));

        return info;
    }

  
      /**
      * 获取用户的权限集合
      */
    protected abstract Set<String> findPermissions(IUser user);
    /**
      * 获取用户的角色集合
      */
    protected abstract Set<String> findRoles(IUser user);

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        UsernamePasswordToken upt = (UsernamePasswordToken) token;
        String username = upt.getUsername();
        char[] password = upt.getPassword();
        if (StringUtils.isBlank(username)) {
            throw new MustUsernameException();
        }

        if (password == null || password.length == 0) {
            throw new MustPasswordException();
        }

        IUser user = userService.findUserByUsername(username);
        if (user == null) {
            throw new UnknownAccountException();
        }

        if (Boolean.TRUE.equals(user.getLocked())) {
            throw new LockedAccountException();
        }

        if (Boolean.TRUE.equals(user.getDisabled())) {
            throw new DisabledAccountException();
        }

        AuthenticationInfo authenticationInfo = assertAuthenticationInfo(user);

        return authenticationInfo;
    }

    protected AuthenticationInfo assertAuthenticationInfo(IUser user) {
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user, user.getPassword(), getName());
        return authenticationInfo;
    }

    protected void assertCredentialsMatch(AuthenticationToken token, AuthenticationInfo info)
            throws AuthenticationException {
        CredentialsMatcher cm = getCredentialsMatcher();
        if (cm != null) {
            if (!cm.doCredentialsMatch(token, info)) {
                throw new IncorrectCredentialsException();
            }
        } else {
            throw new AuthenticationException("A CredentialsMatcher must be configured in order to verify "
                    + "credentials during authentication.  If you do not wish for credentials to be examined, you "
                    + "can configure an " + AllowAllCredentialsMatcher.class.getName() + " instance.");
        }
    }

    public IUserService getUserService() {
        return userService;
    }

    public void setUserService(IUserService userService) {
        this.userService = userService;
    }

IUser也是一个接口,包括用户基本登录信息,方便每个用到的项目自己做实现

public interface IUser {

    String getUsername();

    String getPassword();

    Boolean getDisabled();

    Integer getDeleted();

    Boolean getLocked();

}

3、登录成功回调(重写FormAuthenticationFilter)

比如登录成功后需要修改用户最后登录时间,登录ip,记录日志等等操作都可以在这里进行。

public class KaptchaFormAuthenticationFilter extends FormAuthenticationFilter {
    
    final Logger logger = LoggerFactory.getLogger(getClass());
    
    private MessageSourceAccessor messageSourceAccessor;
    
    public KaptchaFormAuthenticationFilter(MessageSourceAccessor messageSourceAccessor) {
        this.messageSourceAccessor = messageSourceAccessor;
    }

    protected boolean onAccessDenied(ServletRequest request, ServletResponse response, Object mappedValue)
            throws Exception {
        if (request.getAttribute(getFailureKeyAttribute()) != null) {
            return true;
        }
        return super.onAccessDenied(request, response, mappedValue);
    }

    @Override
    protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request,
            ServletResponse response) throws Exception {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        HttpServletResponse httpServletResponse = (HttpServletResponse) response;
        if ("XMLHttpRequest".equalsIgnoreCase(httpServletRequest.getHeader("X-Requested-With"))) {
            httpServletResponse.setCharacterEncoding("UTF-8");
            PrintWriter out = null;
            try{
                out = httpServletResponse.getWriter();
                out.println(FastJsonUtils.toJSONString(ResultModel.defaultSuccess(null)));
                out.flush();
            }finally{
                if(out != null){
                    out.close();
                }
            }
            return false;
        }
        
        return super.onLoginSuccess(token, subject, request, response);
        
    }

    @Override
    protected boolean onLoginFailure(AuthenticationToken token, AuthenticationException e, ServletRequest request,
            ServletResponse response) {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        HttpServletResponse httpServletResponse = (HttpServletResponse) response;
        if ("XMLHttpRequest".equalsIgnoreCase(httpServletRequest.getHeader("X-Requested-With"))) {
            String className = e.getClass().getName();
            ResultModel rm = new ResultModel(ResultStatus.FAIL.getCode(), messageSourceAccessor.getMessage(className));
            PrintWriter out = null;
            try {
                out = httpServletResponse.getWriter();
                out.println(FastJsonUtils.toJSONString(rm));
                out.flush();
            } catch (IOException e1) {
                if(logger.isInfoEnabled()){
                    e1.printStackTrace();
                }
            }finally{
                if(out != null){
                    out.close();
                }
            }
            return false;
        }
        return super.onLoginFailure(token, e, request, response);
    }

    public MessageSourceAccessor getMessageSourceAccessor() {
        return messageSourceAccessor;
    }

    public void setMessageSourceAccessor(MessageSourceAccessor messageSourceAccessor) {
        this.messageSourceAccessor = messageSourceAccessor;
    }

4、springboot配置shiroConfig

package com.mos.easyboot.admin.config;

import com.google.common.collect.Maps;
import com.mos.easyboot.admin.config.service.impl.PermissionService;
import com.mos.easyboot.admin.config.service.impl.UserService;
import com.mos.easyboot.tools.shiro.KaptchaValidateFilter;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.filter.authc.LogoutFilter;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.config.MethodInvokingFactoryBean;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.support.MessageSourceAccessor;

import javax.servlet.Filter;
import java.util.Map;

/**
 * @author 小尘哥
 */
@Configuration
public class ShiroConfig{


    @Bean(name = "securityManager")
    public DefaultWebSecurityManager securityManager(PermissionService permissionService) {
        DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
        manager.setRealm(userRealm(permissionService));
        return manager;
    }

    @Bean
    public MethodInvokingFactoryBean setSecurityManager(PermissionService permissionService) {
        MethodInvokingFactoryBean methodInvokingFactoryBean = new MethodInvokingFactoryBean();
        methodInvokingFactoryBean.setStaticMethod("org.apache.shiro.SecurityUtils.setSecurityManager");
        methodInvokingFactoryBean.setArguments(securityManager(permissionService));
        return methodInvokingFactoryBean;
    }

    @Bean
    @DependsOn(value = "lifecycleBeanPostProcessor")
    public UserRealm userRealm(PermissionService permissionService) {
        UserRealm userRealm = new UserRealm(permissionService);
        userRealm.setCredentialsMatcher(credentialsMatcher());
        return userRealm;
    }

    @Bean
    public HashedCredentialsMatcher credentialsMatcher() {
        HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
        credentialsMatcher.setHashAlgorithmName("MD5");
//        credentialsMatcher.setHashIterations(2); MD5加密迭代次数1:MD5(str),2:MD5(MD5(str))
        return credentialsMatcher;
    }

    @Bean
    public FormAuthenticationFilter authcFilter(@Qualifier("messageSourceAccessor") MessageSourceAccessor messageSourceAccessor,
                                                @Qualifier("userService") UserService userService) {
        CustomFormAuthenticationFilter authenticationFilter = new CustomFormAuthenticationFilter(messageSourceAccessor,userService);
        authenticationFilter.setLoginUrl("/login");
        return authenticationFilter;
    }

    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(
            @Qualifier("permissionService") PermissionService permissionService) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager(permissionService));
        return authorizationAttributeSourceAdvisor;
    }

    public LogoutFilter logoutFilter() {
        LogoutFilter logout = new LogoutFilter();
        logout.setRedirectUrl("/login");
        return logout;
    }
    @Bean
    public KaptchaValidateFilter kaptchaValidate() {
        return new KaptchaValidateFilter();
    }

    @Bean(name = "shiroFilter")
    public ShiroFilterFactoryBean shiroFilter(@Qualifier("messageSourceAccessor") MessageSourceAccessor messageSourceAccessor,
                                              @Qualifier("userService") UserService userService,
                                              @Qualifier("permissionService") PermissionService permissionService) {
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        bean.setSecurityManager(securityManager(permissionService));
        bean.setLoginUrl("/toLogin");
        bean.setUnauthorizedUrl("/unauthor");
        bean.setSuccessUrl("/index");

        Map<String, Filter> filters = Maps.newHashMap();
        filters.put("kaptchaValidate", kaptchaValidate());
        filters.put("authc", authcFilter(messageSourceAccessor,userService));
        filters.put("logout", logoutFilter());
        bean.setFilters(filters);

        Map<String, String> filterChainDefinitionMap = Maps.newHashMap();
        filterChainDefinitionMap.put("/toLogin", "anon");
        filterChainDefinitionMap.put("/login*", "kaptchaValidate,authc");
        filterChainDefinitionMap.put("/logout", "logout");
        filterChainDefinitionMap.put("/demo/**", "anon");
        filterChainDefinitionMap.put("/kaptcha.jpg", "anon");
        filterChainDefinitionMap.put("/app/**", "anon");
        filterChainDefinitionMap.put("/images/**", "anon");
        filterChainDefinitionMap.put("/css/**", "anon");
        filterChainDefinitionMap.put("/js/**", "anon");
        filterChainDefinitionMap.put("/plugins/**", "anon");
        filterChainDefinitionMap.put("/**", "user");

        bean.setFilterChainDefinitionMap(filterChainDefinitionMap);

        return bean;
    }

    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    @Bean
    public MessageSourceAccessor messageSourceAccessor(@Qualifier("messageSource") MessageSource messageSource){
        return new MessageSourceAccessor(messageSource);
    }
}

5、添加shiro拦截

    @Bean
    public FilterRegistrationBean shiroFilterRegistration() {
        FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
        filterRegistration.setFilter(new DelegatingFilterProxy("shiroFilter"));
        filterRegistration.setEnabled(true);
        filterRegistration.addUrlPatterns("/*");
        filterRegistration.setDispatcherTypes(DispatcherType.REQUEST);
        return filterRegistration;
    }

6、使用

controller直接加@RequiresPermissions("对应的权限")或@RequiresRoles("对应的角色")即可
模板上:<@shiro.hasPermission name="你定义的权限标识">/@shiro.hasPermission

7、其他

有些代码没有贴出来,随后我会把整个项目开源出来,easy-boot,基于springboot的快速开发框架搭建方案,希望大家多多支(tu)持(cao)····

目录
相关文章
|
2月前
|
Java Maven Docker
gitlab-ci 集成 k3s 部署spring boot 应用
gitlab-ci 集成 k3s 部署spring boot 应用
|
3月前
|
安全 Java Apache
SpringBoot+Shiro(一)
SpringBoot+Shiro(一)
|
2月前
|
安全 Java 数据库
shiro学习一:了解shiro,学习执行shiro的流程。使用springboot的测试模块学习shiro单应用(demo 6个)
这篇文章是关于Apache Shiro权限管理框架的详细学习指南,涵盖了Shiro的基本概念、认证与授权流程,并通过Spring Boot测试模块演示了Shiro在单应用环境下的使用,包括与IniRealm、JdbcRealm的集成以及自定义Realm的实现。
50 3
shiro学习一:了解shiro,学习执行shiro的流程。使用springboot的测试模块学习shiro单应用(demo 6个)
|
28天前
|
消息中间件 监控 Java
您是否已集成 Spring Boot 与 ActiveMQ?
您是否已集成 Spring Boot 与 ActiveMQ?
52 0
|
2月前
|
Java API Apache
Springboot+shiro,完整教程,带你学会shiro
这篇文章提供了一个完整的Apache Shiro与Spring Boot结合使用的教程,包括Shiro的配置、使用以及在非Web和Web环境中进行身份验证和授权的示例。
103 2
Springboot+shiro,完整教程,带你学会shiro
|
2月前
|
前端开发 Java Apache
Springboot整合shiro,带你学会shiro,入门级别教程,由浅入深,完整代码案例,各位项目想加这个模块的人也可以看这个,又或者不会mybatis-plus的也可以看这个
本文详细讲解了如何整合Apache Shiro与Spring Boot项目,包括数据库准备、项目配置、实体类、Mapper、Service、Controller的创建和配置,以及Shiro的配置和使用。
536 1
Springboot整合shiro,带你学会shiro,入门级别教程,由浅入深,完整代码案例,各位项目想加这个模块的人也可以看这个,又或者不会mybatis-plus的也可以看这个
|
2月前
|
NoSQL Java Redis
shiro学习四:使用springboot整合shiro,正常的企业级后端开发shiro认证鉴权流程。使用redis做token的过滤。md5做密码的加密。
这篇文章介绍了如何使用Spring Boot整合Apache Shiro框架进行后端开发,包括认证和授权流程,并使用Redis存储Token以及MD5加密用户密码。
42 0
shiro学习四:使用springboot整合shiro,正常的企业级后端开发shiro认证鉴权流程。使用redis做token的过滤。md5做密码的加密。
|
1月前
|
JavaScript NoSQL Java
CC-ADMIN后台简介一个基于 Spring Boot 2.1.3 、SpringBootMybatis plus、JWT、Shiro、Redis、Vue quasar 的前后端分离的后台管理系统
CC-ADMIN后台简介一个基于 Spring Boot 2.1.3 、SpringBootMybatis plus、JWT、Shiro、Redis、Vue quasar 的前后端分离的后台管理系统
47 0
|
4月前
|
SQL Java 数据库连接
springboot+mybatis+shiro项目中使用shiro实现登录用户的权限验证。权限表、角色表、用户表。从不同的表中收集用户的权限、
这篇文章介绍了在Spring Boot + MyBatis + Shiro项目中,如何使用Shiro框架实现登录用户的权限验证,包括用户、角色和权限表的设计,以及通过多个表查询来收集和验证用户权限的方法和代码实现。
springboot+mybatis+shiro项目中使用shiro实现登录用户的权限验证。权限表、角色表、用户表。从不同的表中收集用户的权限、
|
4月前
|
SQL 前端开发 Java
springboot项目中使用shiro实现用户登录以及权限的验证
这篇文章详细介绍了如何在Spring Boot项目中集成Apache Shiro框架来实现用户登录和权限验证,包括项目依赖配置、数据库连接、实体类定义、控制器、服务层、Mapper层以及前端页面的实现,并展示了实际效果和过滤器代码。
springboot项目中使用shiro实现用户登录以及权限的验证