springboot shiro权限管理

1 篇文章 0 订阅
1 篇文章 0 订阅
  1. pom.xml
<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
</dependency>
    
<dependency>
	<groupId>org.apache.shiro</groupId>
	<artifactId>shiro-core</artifactId>
</dependency>
<dependency>
	<groupId>org.apache.shiro</groupId>
	<artifactId>shiro-spring</artifactId>
</dependency>
<dependency>
	<groupId>com.alibaba</groupId>
	<artifactId>fastjson</artifactId>
</dependency>
<dependency>
	<groupId>javax.servlet</groupId>
  	<artifactId>jstl</artifactId>
</dependency>

  1. 密码校验规则
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.SimpleCredentialsMatcher;

/**
 * 2.密码校验规则
 * 传入的密码与数据库密码比较
 * 重写 doCredentialsMatch 方法
 */
public class CredentialsMatcher extends SimpleCredentialsMatcher {

    @Override
    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
        UsernamePasswordToken token1 = (UsernamePasswordToken)token;
        //密码加密1--3次
        //token中传过来的密码
        String password = new String (token1.getPassword());
        //数据库密码
        String dbPassWord = (String) info.getCredentials();
        return this.equals(password,dbPassWord);
    }
}
  1. shiro配置类
import org.apache.shiro.cache.MemoryConstrainedCacheManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
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.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;

import java.util.LinkedHashMap;

 @Configuration
public class ShiroConfiguration {

	/**
	 * 4.Shiro的过滤器 命名:shiroFilter
	 * 返回工厂bean : ShiroFilterFactoryBean
	 */
	@Bean(name = "shiroFilter")
	public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("securityManager")SecurityManager securityManager) {
		ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
		//Shiro的核心安全接口,创建实例注入自己的securityManager
		bean.setSecurityManager(securityManager);
		// bean.setLoginUrl("login");
			LinkedHashMap<String, Filter> filterMap = new LinkedHashMap<>();
		filterMap.put("authc", new AjaxPermissionsAuthorizationFilter());
	    bean.setFilters(filterMap);
		/*定义shiro过滤链  Map结构
		 * Map中key(xml中是指value值)的第一个'/'代表的路径是相对于HttpServletRequest.getContextPath()的值来的
		 * anon:它对应的过滤器里面是空的,什么都没做,这里.do和.jsp后面的*表示参数,比方说login.jsp?main这种
		 * authc:该过滤器下的页面必须验证后才能访问,它是Shiro内置的一个拦截器org.apache.shiro.web.filter.authc.FormAuthenticationFilter
		 */
		//拦截的map
		LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
         /* 过滤链定义,从上向下顺序执行,一般将 /** 放在最为下边;
          * authc:所有url都必须认证通过才可以访问;
          * anon:所有url都都可以匿名访问
          */
		// 默认的过滤定义在DefaultFilter类中
		filterChainDefinitionMap.put("/", "anon");
		filterChainDefinitionMap.put("/static/**", "anon");
		filterChainDefinitionMap.put("/login", "anon");
		filterChainDefinitionMap.put("/login_out", "anon");
		filterChainDefinitionMap.put("/error", "anon");
		// filterChainDefinitionMap.put("/list", "roles[管理员]"); //是这个角色可以访问
		filterChainDefinitionMap.put("/**", "authc");
		bean.setFilterChainDefinitionMap(filterChainDefinitionMap);
		return bean;
	}

	/**
	 * 3.不指定名字的话,自动创建一个方法名第一个字母小写的bean
	 * 安全管理器
	 */
	@Bean("securityManager")
	public SecurityManager securityManager(@Qualifier("userRealm")UserRealm userRealm) {
		DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
		securityManager.setRealm(userRealm);
		return securityManager;
	}

	/**
	 * 2.Shiro Realm 继承自AuthorizingRealm的自定义Realm,
	 * 即指定Shiro验证用户登录的类为自定义的
	 * CredentialsMatcher为上下文 1.credentialsMatcher
	 */
	@Bean(name = "userRealm")
	public UserRealm userRealm(@Qualifier("credentialsMatcher") CredentialsMatcher matcher) {
		UserRealm userRealm = new UserRealm();
		//验证存储到缓存Cache中
		userRealm.setCacheManager(new MemoryConstrainedCacheManager());
		//使用自己的密码校验器
		userRealm.setCredentialsMatcher(matcher);
		return userRealm;
	}

	/**
	 * 1.密码校验规则
	 */
	@Bean(name = "credentialsMatcher")
	public CredentialsMatcher credentialsMatcher() {
		return new CredentialsMatcher();
	}

	/**
	 * 5.配置Shiro和Spring关联
	 * @return
	 */
	@Bean
	public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager")SecurityManager securityManager ) {
		AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
		advisor.setSecurityManager(securityManager);
		return advisor;
	}

	/**
	 * 6.开启Shiro的注解(如@RequiresRoles,@RequiresPermissions),
	 * 需借助SpringAOP扫描使用Shiro注解的类,并在必要时进行安全逻辑验证
	 * 配置以下两个bean(DefaultAdvisorAutoProxyCreator(可选)
	 * 和AuthorizationAttributeSourceAdvisor)即可实现此功能
	 */
	@Bean
	@DependsOn({"lifecycleBeanPostProcessor"})
	public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {
		//使用代理
		DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
		//默认值更改为true
		creator.setProxyTargetClass(true);
		return creator;
	}


	/**
	 * Shiro生命周期处理器
	 */
	@Bean
	public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
		return new LifecycleBeanPostProcessor();
	}
  1. 自定义Realm实现认证授权
@Slf4j
public class UserRealm extends AuthorizingRealm {

	@Autowired
	private SystemAdminService systemAdminService;


	/**
	 * 授权
	 * 认证成功登陆之后
	 * 从session中取值
	 * @param principals
	 * @return
	 */
	@Override
	@SuppressWarnings("unchecked")
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		//获取对象(第一种)
		SystemAdminVo user = (SystemAdminVo) principals.fromRealm(this.getClass().getName()).iterator().next();
		//从session中获取内容(第二种)
		//Session session = SecurityUtils.getSubject().getSession();
		//查询用户的权限
		//JSONObject permission = (JSONObject) session.getAttribute(DataPool.SESSION_USER_PER);
		SystemRole roles = user.getRoles(); //角色

		//Map<String,Object> permissionList = new HashMap<>();
		Set<String> set = new HashSet<>();
		if(null != roles){
			Set<SystemPermission> permissionSet = roles.getPermissionList();
			if(CollectionUtils.isNotEmpty(permissionSet)){
				for(SystemPermission permission : permissionSet){
					set.add(permission.getPermissionCode());
				}
			}
		}
		//为当前用户设置角色和权限
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		info.addStringPermissions(set); /* 权限 */
		info.addRole(roles.getRoleName()); /* 角色授权 */
		return info;
	}

	/**
	 * 验证当前登录的Subject
	 * 认证登陆
	 * LoginController.login()方法中执行Subject.login()时 执行此方法
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
		//强转成UsernamePasswordToken
		UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken)authcToken;
		//取出对应的登陆名验证
		String loginName = usernamePasswordToken.getUsername();
		//获取对应的用户
		SystemAdminVo user = systemAdminService.getFindByLoginName(loginName);
		if (user == null) {
			//没找到帐号
			throw new UnknownAccountException();
		}
		//交给AuthenticatingRealm使用CredentialsMatcher进行密码匹配
		SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user,user.getPassword(),this.getClass().getName());
		//将用户信息放入session中
//SecurityUtils.getSubject().getSession().setAttribute(DataPool.SESSION_USER, user);
		return authenticationInfo;
	}
}
  1. 对没有登录的请求进行拦截过滤
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import com.alibaba.fastjson.JSONObject;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;

/**
 * 对没有登录的请求进行拦截,
 * 全部返回json信息.
 * 覆盖掉shiro原本的跳转login.jsp的拦截方式
 *
 */
public class AjaxPermissionsAuthorizationFilter extends FormAuthenticationFilter {

	@Override
	protected boolean onAccessDenied(ServletRequest request, ServletResponse response) {
		 JSONObject jsonObject = new JSONObject();
		 jsonObject.put("code", ErrorEnum.E_1000.getErrorCode());
		 jsonObject.put("msg", ErrorEnum.E_1000.getErrorMsg());
		PrintWriter out = null;
		HttpServletResponse res = (HttpServletResponse) response;
		try {
			res.setCharacterEncoding("UTF-8");
			res.setContentType("application/json");
			out = response.getWriter();
			out.println(jsonObject);
		} catch (Exception e) {
		} finally {
			if (null != out) {
				out.flush();
				out.close();
			}
		}
		return false;
	}

	@Bean
	public FilterRegistrationBean registration(AjaxPermissionsAuthorizationFilter filter) {
		FilterRegistrationBean registration = new FilterRegistrationBean(filter);
		registration.setEnabled(false);
		return registration;
	}
}
  1. 错误枚举定义
public enum ErrorEnum {
	/*
	 * 错误信息
	 * */

	E_1000("1000", "登陆已过期,请重新登陆");

	private String errorCode;

	private String errorMsg;

	ErrorEnum(String errorCode, String errorMsg) {
		this.errorCode = errorCode;
		this.errorMsg = errorMsg;
	}

	public String getErrorCode() {
		return errorCode;
	}

	public String getErrorMsg() {
		return errorMsg;
	}

}
  1. 接口
/**
     * 登录
     * @param loginName:登录账号
     * @param password:登录密码
     */
    @GetMapping("/login")
    public JsonObject login(@RequestParam String loginName, @RequestParam String password) {
        //获取对应的用户
        UsernamePasswordToken token = new UsernamePasswordToken(loginName, password);
        Subject subject = SecurityUtils.getSubject();
        //shiro的认证逻辑
        subject.login(token);
        //账户信息
        SystemAdminVo vo = (SystemAdminVo)subject.getPrincipal();
        //权限信息vo.getRoles().getPermissionList()
        //转json处理
        return "返回json对象";
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot集成Shiro进行权限控制的步骤如下: 1. 引入Shiro和Spring Boot相关依赖。 2. 配置Shiro相关的Bean,包括Realm、SecurityManager和Filter等。 3. 配置Shiro的拦截器,即设置需要拦截的URL和对应的权限。 4. 在Controller中使用注解进行权限控制。 以下是一个简单的示例: 1. 引入依赖,在pom.xml文件中添加以下内容: ``` <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.4.1</version> </dependency> ``` 2. 配置Shiro相关的Bean,创建一个ShiroConfig类,并添加以下内容: ``` @Configuration public class ShiroConfig { @Bean public Realm realm() { // 创建自定义的Realm return new MyRealm(); } @Bean public SecurityManager securityManager() { // 创建SecurityManager,并设置Realm DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(realm()); return securityManager; } @Bean public ShiroFilterFactoryBean shiroFilter() { // 创建ShiroFilterFactoryBean,并设置SecurityManager和拦截器 ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean(); shiroFilter.setSecurityManager(securityManager()); Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>(); filterChainDefinitionMap.put("/login", "anon"); filterChainDefinitionMap.put("/logout", "logout"); filterChainDefinitionMap.put("/**", "authc"); shiroFilter.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilter; } } ``` 3. 配置Shiro的拦截器,创建一个WebMvcConfig类,并添加以下内容: ``` @Configuration public class WebMvcConfig implements WebMvcConfigurer { @Autowired private ShiroFilterFactoryBean shiroFilter; @Override public void addInterceptors(InterceptorRegistry registry) { // 添加Shiro拦截器 registry.addInterceptor(new ShiroInterceptor()).addPathPatterns("/**"); } @Bean public HandlerInterceptor shiroInterceptor() { // 创建ShiroInterceptor,并设置ShiroFilterFactoryBean ShiroInterceptor shiroInterceptor = new ShiroInterceptor(); shiroInterceptor.setShiroFilter(shiroFilter); return shiroInterceptor; } } ``` 4. 在Controller中使用注解进行权限控制,例如: ``` @RestController public class UserController { @GetMapping("/user") @RequiresPermissions("user:view") public String viewUser() { // 只有具有user:view权限的用户才能访问 return "View User"; } } ``` 以上是Spring Boot集成Shiro进行权限控制的基本步骤,具体实现还需要根据实际情况进行调整。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值