web项目整合shiro

一、shiro介绍

借用官方的话:Apache Shiro是一个功能强大、易于使用的Java安全框架,它常用于身份验证、授权、加密和会话管理。Shiro的API易于理解,您可以快速轻松地保护任何应用程序——从小的移动应用程序到大的Web和企业应用程序。

官网:https://shiro.apache.org/

二、spring boot整合shiro

1.maven资源

我使用的版本是1.4.0

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

2.shiroConfig 配置类:注释很详细,缓冲如果不需要可以不要,shiro默认有一套缓存规则。

package com.cn.iris.common.config;

import com.cn.iris.common.core.shiro.LoginRealm;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.SimpleCredentialsMatcher;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cache.ehcache.EhCacheManagerFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * Author: IrisNew
 * Description: shiro 配置
 * Date: 2018/6/6 16:45
 */
@Configuration
public class ShiroConfig {

    /**
     * 缓存管理器 使用Ehcache实现
     */
    @Bean
    public CacheManager getCacheShiroManager(EhCacheManagerFactoryBean ehcache) {
        EhCacheManager ehCacheManager = new EhCacheManager();
        ehCacheManager.setCacheManager(ehcache.getObject());
        return ehCacheManager;
    }

    /**
     * ShiroFilterFactoryBean 处理拦截资源文件问题
     * 初始化ShiroFilterFactoryBean的时候需要注入:SecurityManager
     *
     */
    @Bean(name = "shiroFilter")
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") SecurityManager securityManager){
        ShiroFilterFactoryBean sfbBean = new ShiroFilterFactoryBean();
        sfbBean.setSecurityManager(securityManager);
        //设置默认登陆页
        sfbBean.setLoginUrl("/welcome");
        //登陆成功后跳转的url
        sfbBean.setSuccessUrl("/index");
        //设置权限不足跳转
        sfbBean.setUnauthorizedUrl("/403");
        //自定义过滤器
        /*Map<String, Filter> filters=new HashMap<>();
        filters.put("per",getPermissionFilter());
        filters.put("verCode",getVerfityCodeFilter());
        sfbBean.setFilters(filters);*/

        /** 配置访问权限
         * 过滤链定义,从上向下顺序执行,一般将/**放在最为下边
         * anon  不需要认证
         * authc 需要认证
         */
        Map<String, String> filterMap = new LinkedHashMap<>();
        filterMap.put("/css/**","anon");
        filterMap.put("/js/**","anon");
        filterMap.put("/welcome","anon");
        filterMap.put("/userlogin","anon");
        filterMap.put("/getVeCode","anon");
        filterMap.put("/logout","logout");
        filterMap.put("/plugin/**","anon");
        filterMap.put("/**","authc");
        sfbBean.setFilterChainDefinitionMap(filterMap);
        return sfbBean;
    }

    // 配置核心安全事务管理器
    @Bean(name = "securityManager")
    public SecurityManager securityManager(@Qualifier("loginRealm") LoginRealm loginRealm,CacheManager cacheShiroManager) {
        DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
        //自定义的权限登录器
        manager.setRealm(loginRealm);
        //自定义的session管理器
//        manager.setSessionManager(sessionManager);
        //自定义缓存策略
        manager.setCacheManager(cacheShiroManager);
        return manager;
    }

    //配置自定义的权限登录器
    @Bean(name = "loginRealm")
    public LoginRealm getLoginRealm(){
        LoginRealm realm= new LoginRealm();
        realm.setCredentialsMatcher(credentialsMatcher());
        return realm;
    }

    // 配置自定义的密码匹配比较器
    @Bean(name = "credentialsMatcher")
    public CredentialsMatcher credentialsMatcher() {
        return new SimpleCredentialsMatcher();
    }

    /**
     * 启用shrio授权注解拦截方式,AOP式方法级权限检查
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(@Qualifier("securityManager") SecurityManager securityManager){
        AuthorizationAttributeSourceAdvisor as=new AuthorizationAttributeSourceAdvisor();
        as.setSecurityManager(securityManager);
        return as;
    }
}

3.自定义Realm,这个是所有用shiro都需要自定义的。

其中userServiceImpl的findByAcc方法是用账号查询用户实体返回;

role2menuService的getMenuCodesByRoleIds方法是用来查询角色对应的所有菜单及增删改查权限的。

package com.cn.iris.common.core.shiro;

import com.cn.iris.admin.entity.User;
import com.cn.iris.admin.service.IRole2menuService;
import com.cn.iris.admin.service.IUserService;
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.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * Author: IrisNew
 * Description: shiro权限登录器
 * Date: 2018/6/8 16:14
 */
@Service
public class LoginRealm extends AuthorizingRealm {

  @Autowired
  private IUserService userServiceImpl;
  @Autowired
  private IRole2menuService role2menuService;

  // 认证.登录 提供账户信息返回认证信息
  /**
   * 当调用如下代码时会进入这个方法(一般是登录页面)
   * Subject currentUser = SecurityUtils.getSubject();
   * currentUser.login(token);
   */
  @Override
  protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {

    UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken; // 获取用户输入的token

    //输入的用户名
    String userAcc = token.getUsername();
    User user = userServiceImpl.findByAcc(userAcc);

    if (user == null) {
      throw new UnknownAccountException("账号或者密码错误!");
    }
    return new SimpleAuthenticationInfo(user, user.getUserPsw(), getName());
  }

  // 授权
  // 提供用户信息返回权限信息
  @Override
  protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {

    // 获取session中的用户

    User user = (User) principalCollection.getPrimaryPrincipal();
    List<String> roIdsList = user.getRoleIds();
    List<String> permissionsList = role2menuService.getMenuCodesByRoleIds(roIdsList);

    SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
    info.addRoles(roIdsList);
    if(permissionsList != null && permissionsList.size()>0){
      info.addStringPermissions(permissionsList); // 将权限放入shiro中.
    }
    return info;
  }

}

4.工具类,方便获取当前登陆的session及Subject对象。

package com.cn.iris.common.core.shiro;

import com.cn.iris.admin.entity.User;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;

/**
 * Author: IrisNew
 * Description:shiro工具类
 * Date: 2018/6/11 14:48
 */
public class ShiroUtil {

    /**
     * 获取当前 Subject
     */
    public static Subject getSubject(){
        return SecurityUtils.getSubject();
    }

    /**
     * 获取登陆用户
     */
    public static User getUser(){
        return (User)getSubject().getPrincipals().getPrimaryPrincipal();
    }

    /**
     * 验证用户是否属于某角色
     */
    public boolean hasRole(String roleName) {
        return getSubject() != null && roleName != null && roleName.length() > 0 && getSubject().hasRole(roleName);
    }

    /**
     * 验证用户是否拥有指定权限
     */
    public boolean hasPermission(String permission) {
        Subject subject = getSubject();
        return getSubject() != null && permission != null
                && permission.length() > 0
                && getSubject().isPermitted(permission);
    }

    public static Session getSession(){
        return getSubject().getSession();
    }
}

5.登陆及登出调用(代码段)

    @GetMapping("/userlogin")
    public String index(HttpServletRequest request, String userAcc, String userPsw) {
        
        Subject subject = ShiroUtil.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(userAcc.trim(),userPsw);
        subject.login(token);

        User user = userServiceImpl.findByAcc(userAcc);
        if(user.getUserPsw().equals(userPsw)){
            logger.info("用户登陆:"+user.getNickName());
            return "redirect:/index";
        }
        return "login";
    }


    //跳转至登陆页
    @GetMapping("/logOut")
    public String logOut() {
        ShiroUtil.getSubject().logout();
        return "/login";
    }

前端页面就不将代码贴出来了。

我本人的自己写了个简单的springboot项目,整合了shiro,是一套完整的项目管理类项目,开源免费。

感兴趣的可以看看:Iris-开源的后台管理类项目;希望能高台贵手,给小弟一个star.感谢!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值