SHIRO安全框架介绍与使用

Shiro:能够执行身份验证,授权,加密,会话管理(全局session)

shiro:操作中对象与方法

  • Subject : 当前操作用户,即当前与shiro进行交互的应用

  • SecurityManager:Shiro通过该方法来管理内部组件实例,并提供安全管理的各种服务

  • Realm:安全数据源(认证和授权数据),配置Shiro时,至少指定一个Realm,用户认证授权(Shiro内置了可连接大量安全数据源的Realm,若默认Realm不满足需求,则可以自动以Realm)

SpringBoot 集成 Shiro

引入依赖

<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring-boot-web-starter</artifactId>
    <version>版本号</version>
</dependency>
<!-- 版本号根据项目设计管理更改 1.4.0 -->

application.properties中配置shiro

#shiro配置
#默认初始路径
shiro.loginUrl=/safty/login/toLogin
#shiro 的 记住我 功能开启后的默认路径
shiro.successUrl=/safty/home/toHome
#认证失败后跳转路径
shiro.unauthorizedUrl=/safty/login/toLogin
#使用shiro本地session非HttpSession shiro会自动同步
shiro.userNativeSessionManager=true
#日志级别设置
#logging.level.全类名=debug

自定义Realm

package com.johe.scgcxx.base;

import java.text.MessageFormat;
import java.util.List;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.cache.MemoryConstrainedCacheManager;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;

import com.johe.scgcxx.dto.Curr_User;
import com.johe.scgcxx.dto.Menu;
import com.johe.scgcxx.model.Sys_Module;
import com.johe.scgcxx.model.Sys_User;
import com.johe.scgcxx.service.base.ShiroService;

@Configuration
public class DefaultShiro {
        //日志对象
	private static final Logger LOG = LoggerFactory.getLogger(DefaultShiro.class);

	/**
	 * Bean注解名 必须为 authorizer
	 */
	@Bean("authorizer")
	@Autowired
	public AuthorizingRealm saftyRealm(ShiroService shiroService) {
		return new AuthorizingRealm() {
			/**
			 * 获取当前用户授权信息,shiro检查需要通过该方法获取授权信息 参数为 当前用户集合
                         * 该方法会在shiro 过滤方法中 配置的路径 进行权限认证时执行
			 */
			@Override
			protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
				// 获取用户账号
				Curr_User currUser = (Curr_User) principals.getPrimaryPrincipal();// 获取首要当事人
				// 创建授权信息对象
				SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
				// 查询用户权限,并放入授权对象
				List<Menu> menuList = shiroService.getModuleByCurrUserID(currUser.getU_id());
				for (Menu menu : menuList) {
					simpleAuthorizationInfo.addStringPermission(String.valueOf(menu.getMenu_id()));
				}
				return simpleAuthorizationInfo;

			}

			/**
			 * 授权认证信息(当前用户信息,账号,密码) shiro在登录认证时需要通过该方法获取认证信息, 参数认证令牌,(一组用户名和密码)
			 */
			@Override
			protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)
					throws AuthenticationException {
				String u_id = (String) token.getPrincipal();
				Sys_User user = shiroService.getCurrUser(u_id);
				if (user == null) {
					return null;
				}
				// 若该用户存在,创建当前用户
				Curr_User currUser = new Curr_User(user.getU_id(), user.getU_name());
				/**
				 * 创建认证信息 参数 1 当前用户 2认证凭证 3realm名称
                                 * 该操作会将 当前用户存储到shiro内置对象principal中
				 */
				SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(currUser, user.getU_pwd(), this.getName());
				return info;
			}

		};
	}

	// 设置Shiro默认过滤器(应用启动时执行路径的权限过滤)
	@Bean
	@Autowired
	public ShiroFilterChainDefinition shiroFilterChainDefinition(ShiroService shiroService) {
		DefaultShiroFilterChainDefinition shiroFilter = new DefaultShiroFilterChainDefinition();
		shiroFilter.addPathDefinition("/css/**", "anon");
		shiroFilter.addPathDefinition("/elementui/**", "anon");
		shiroFilter.addPathDefinition("/js/**", "anon");
		shiroFilter.addPathDefinition("/safty/login/**", "anon");
		// 加载动态权限
		List<Sys_Module> moduleList = shiroService.getAllSubModules();

		String PREMISSION_FORMAT = "authc,perms[{0}]";

		// 由注入的资源管理对象获取所有资源数据,并且资源的authorities的属性是EAGER的fetch类型
		for (Sys_Module sys_Module : moduleList) {
			if (StringUtils.isEmpty(sys_Module.getM_url())) {
				continue;
			}
			shiroFilter.addPathDefinition(sys_Module.getM_url().replace("toList", "**"),
					MessageFormat.format(PREMISSION_FORMAT, String.valueOf(sys_Module.getM_id())));
		}

		// 其他资源必须经过认证
		shiroFilter.addPathDefinition("/**", "authc");

		LOG.debug("===========shiro校验==============");
		LOG.debug(shiroFilter.getFilterChainMap().toString());
		LOG.debug("===========shiro校验==============");

		return shiroFilter;
	}

}

登录与退出(ResultUtils为 自定义MAP结果返回,**Service为 自定义业务操作)

package com.johe.scgcxx.controller.safty;

import java.util.List;

import javax.servlet.http.HttpSession;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.johe.scgcxx.base.Constants;
import com.johe.scgcxx.base.ResultUtils;
import com.johe.scgcxx.dto.Curr_User;
import com.johe.scgcxx.dto.Menu;
import com.johe.scgcxx.dto.Sys_User;
import com.johe.scgcxx.service.safty.SaftyLoginService;

//安全管理-用户登录
@Controller
public class SaftyLoginController {
	@Autowired
	private SaftyLoginService saftyLoginService;
	
	
	@RequestMapping("/safty/login/doLogin")
	@ResponseBody
	public ResultUtils toLogin(@RequestBody Sys_User user,HttpSession session) {
		try {
		Subject subject = SecurityUtils.getSubject();
		//创建登录令牌
		UsernamePasswordToken token = new UsernamePasswordToken(user.getU_id(), user.getU_pwd());
		//登录(该操作会执行realm中授权认证的方法)
		subject.login(token);
		//是否通过认证
		if (subject.isAuthenticated()) {
			//获取当前用户信息
			Curr_User currUser = (Curr_User)subject.getPrincipal();
			//将当前用户放入session
			subject.getSession().setAttribute(Constants.SESSION_CURR_USER_ATTR, currUser);
			
			System.out.println(user.getU_id()+":登录====进入");
			
			return ResultUtils.successResult();
		}
		return ResultUtils.failResult("登录失败!!!");
		
		} catch (UnknownAccountException e) {
			return ResultUtils.failResult("用户名不存在!");
        	
        } catch (IncorrectCredentialsException e) {
        	return ResultUtils.failResult("账户密码 不正确!");
        } catch (LockedAccountException e) {
        	return ResultUtils.failResult("用户名 被锁定 !");
        }catch (Exception e) {
			e.printStackTrace();
			return ResultUtils.failResult("系统错误!");
		}
		
	}
	
	
	@DeleteMapping("/safty/home/doLogout")
	@ResponseBody
	public ResultUtils toLogout() {
		try {
                        //清除shiro内置session信息
			SecurityUtils.getSubject().logout();
			return ResultUtils.successResult();
		} catch (Exception e) {
			return ResultUtils.failResult("退出异常!!!");
		}
	}
	
	
}

shiro权限缓存设置 (无需对每次路由进行权限查询验证(相同路由只需首次进入时验证))

	//该 权限缓存代码 位置 : Shiro自定义realm类中

    //用于设置shiro缓存管理器
    @Bean
	protected CacheManager shiroCacheManager() {
		return new MemoryConstrainedCacheManager();
	}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值