shiro进阶(springboot集成)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_17476231/article/details/92961976

一、表设计

     权限表大体分为三个表:用户表、角色表、权限表,以及用户角色中间表、角色权限表。对应关系是用户角色多对多,角色权限多对多。这只是简单基本的表设计,可以根据需求自己设计。

二、定制realm

package com.shiro.common;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAccount;
import org.apache.shiro.authc.UsernamePasswordToken;
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 com.shiro.dao.PermissionMapper;
import com.shiro.dao.RoleMapper;
import com.shiro.dao.UserMapper;
import com.shiro.entity.Permission;
import com.shiro.entity.Role;
import com.shiro.entity.User;

public class MyShiroRealm extends AuthorizingRealm{
		@Autowired
		private UserMapper usermapper;
		@Autowired
		private RoleMapper rolemapper;
		@Autowired
		private PermissionMapper permissionmapper;
		//每个realm都有一个名字
		static String REALM_NAME="myrealm";
	
		
		
		/**
		 * 支持哪种令牌 
		 */
		@Override
		public boolean supports(AuthenticationToken token) {
			// TODO Auto-generated method stub
			
			return token instanceof UsernamePasswordToken;
		}
		/**
		 * 获取权限过程
		 */
		@Override
		protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
			//获取用户名
			String userName=principals.getPrimaryPrincipal().toString();
			User user=usermapper.getUserByName(userName.trim());
			//构建权限的类
			SimpleAuthorizationInfo sai=new SimpleAuthorizationInfo();
			Set<String> proleList=new HashSet<String>();
			Set<String> stringPermissions=new HashSet<String>();
			if(user!=null){
				List<Role> lrole = rolemapper.getRoleById(user.getUser_id());
				for (Role role : lrole) {
					proleList.add(role.getName());
					List<Permission> plist = permissionmapper.getPermissionById(role.getId());
					for (Permission permission : plist) {
						stringPermissions.add(permission.getName());
					}
				}
			}
			sai.setRoles(proleList);
			sai.setStringPermissions(stringPermissions);
			return sai;
		}
		/**
		 * 认证过程
		 */
		@Override
		protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
			UsernamePasswordToken upt=(UsernamePasswordToken)token;
			String userName=token.getPrincipal().toString();
			String password=String.valueOf(upt.getPassword());
			User user=usermapper.getUserByName(userName.trim());
			if(user!=null){
				String realPwd=user.getPassword();
				if(realPwd.equals(password)){
					SimpleAccount sa=new SimpleAccount(userName,password,"REALM_NAME");
					return sa;
				}
			}
			return null;
		}
}

三、shiro配置类

package com.shiro.common;

import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;

import org.apache.shiro.realm.Realm;
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.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.web.filter.DelegatingFilterProxy;

@Configuration
public class ShiroConfigBean {
	/*
     * 开启Shiro的注解(如@RequiresRoles,@RequiresPermissions),需借助SpringAOP扫描使用Shiro注解的类,并在必要时进行安全逻辑验证
     * 配置以下两个bean(DefaultAdvisorAutoProxyCreator(可选)和AuthorizationAttributeSourceAdvisor)即可实现此功能
     * @return
     */
    @Bean
    @DependsOn({"lifecycleBeanPostProcessor"})
    public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator(){
        DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        advisorAutoProxyCreator.setProxyTargetClass(true);
        return advisorAutoProxyCreator;
    }
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Autowired org.apache.shiro.mgt.SecurityManager securityManager){
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }

	@Bean
	public FilterRegistrationBean webShiroFilter(){
		FilterRegistrationBean frb=new FilterRegistrationBean();
		DelegatingFilterProxy dfp=new DelegatingFilterProxy();
		frb.setFilter(dfp);
		frb.setName("shiroFilter");
		LinkedHashSet<String> linkedHashSet = new LinkedHashSet<String>();
		linkedHashSet.add("/*");
		frb.setUrlPatterns(linkedHashSet);
		
		
		Map<String, String> initParameters=new HashMap<String, String>();
		initParameters.put("targetFilterLifecycle", "true");
		frb.setInitParameters(initParameters);
		return frb;
	}
	/**
	 * 配置我的realm
	 * @return
	 */
	@Bean
	public Realm myRealm(){
		return new MyShiroRealm();
	}
	/**
	 * 定義默認的securityManager
	 * @return
	 */
	@Bean
	public DefaultWebSecurityManager securityManager(@Autowired Realm myRealm){
		DefaultWebSecurityManager dwm=new DefaultWebSecurityManager();
		dwm.setRealm(myRealm);
		return dwm;
	}
	
	/**
	 * 定義和過濾器一致名字的ShiroFilterFactoryBean
	 */
	@Bean
	public ShiroFilterFactoryBean shiroFilter(@Autowired org.apache.shiro.mgt.SecurityManager securityManager){
		ShiroFilterFactoryBean sffb=new ShiroFilterFactoryBean();
		sffb.setSecurityManager(securityManager);
		sffb.setLoginUrl("/login.html");
		sffb.setUnauthorizedUrl("/faliure.html");
		Map<String, String> urls=new HashMap<String, String>();
		urls.put("/login", "anon");
		urls.put("/succeed", "authc");
		urls.put("/data", "roles[role1]");
		sffb.setFilterChainDefinitionMap(urls);
		return sffb;
	}
	/**
	 * 定義後置處理器
	 * @return
	 */
	@Bean
	public LifecycleBeanPostProcessor lifecycleBeanPostProcessor(){
		return new LifecycleBeanPostProcessor();
	}

}

四、登录以及权限限制

package com.shiro.controller;

import javax.servlet.http.HttpServletRequest;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class LoginController {
	@RequestMapping("/getlogin")
	public String getLogin(){
		return "login";
	}
	@RequestMapping("/exit")
	public String exit(){
		Subject currentUser = SecurityUtils.getSubject();
		currentUser.logout(); 
		return "login";
	}
	@RequestMapping("/toData")
	public String toData(){
		return "data";
	}
	@RequestMapping("/login")
	public String login(String username,String password,HttpServletRequest request){
		Subject subject = SecurityUtils.getSubject();
		UsernamePasswordToken upt=new UsernamePasswordToken(username,password);
		try {
			subject.login(upt);
			/*subject.getSession().setAttribute("userInfo","");
            //关键代码 shiro自动保存了上一次请求的地址  只需要获取并重新跳转即可
            //可以使用WebUtils.issueRedirect重定向跳转
			SavedRequest savedRequest = WebUtils.getSavedRequest(request);
			if(savedRequest!=null)
				return "redirect:"+savedRequest.getRequestURI()+"?"+savedRequest.getQueryString();*/
			return "succeed";
		} catch (AuthenticationException e) {
			return "failure";
		}
	}

	@RequiresPermissions({"query"} )
	@RequestMapping("/queryTest")
	@ResponseBody
	public String queryTest(){
		return "0";
	}
	@RequiresPermissions({"insert"} )
	@RequestMapping("/insertTest")
	@ResponseBody
	public String insertTest(){
		return "0";
	}
	@RequiresPermissions({"update"} )
	@RequestMapping("/updateTest")
	@ResponseBody
	public String updateTest(){
		return "0";
	}
	@RequiresPermissions({"delete"} )
	@RequestMapping("/deletTest")
	@ResponseBody
	public String deletTest(){
		return "0";
	}
}

其余代码省略,大概就是查询权限的。

附上权限认证所有注解:

@RequiresAuthentication

验证用户是否登录,等同于方法subject.isAuthenticated() 结果为true时。

@RequiresUser

验证用户是否被记忆,user有两种含义:

一种是成功登录的(subject.isAuthenticated() 结果为true);

另外一种是被记忆的(subject.isRemembered()结果为true)。

@RequiresGuest

验证是否是一个guest的请求,与@RequiresUser完全相反。

 换言之,RequiresUser  == !RequiresGuest。

此时subject.getPrincipal() 结果为null.

@RequiresRoles

例如:@RequiresRoles("aRoleName");

  void someMethod();

如果subject中有aRoleName角色才可以访问方法someMethod。如果没有这个权限则会抛出异常AuthorizationException

@RequiresPermissions

例如: @RequiresPermissions({"file:read", "write:aFile.txt"} )
  void someMethod();

要求subject中必须同时含有file:read和write:aFile.txt的权限才能执行方法someMethod()。否则抛出异常AuthorizationException

转自https://www.cnblogs.com/wudage/p/7305003.html

四、运行效果

猜你喜欢

转载自blog.csdn.net/qq_17476231/article/details/92961976