springboot整合shiro框架做授权和登陆 - yiyanglij/yiyanglij.github.io GitHub Wiki

1:增加shiro相关依赖

 <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-spring-boot-web-starter</artifactId>
        <version>1.4.0</version>
    </dependency>

2:自定义Realm继承AuthorizingRealm

实现两个方法doGetAuthorizationInfo和doGetAuthenticationInfo

doGetAuthorizationInfo: 该方法用于定义用户在shiro中的安全权限,也就是说我们可以在这个方法中告诉shiro当前登录的用户具有访问哪些路径或资源的权限;

  package com.example.realm;

  import com.example.entity.Permission;
  import com.example.entity.Role;
  import com.example.entity.User;
  import com.example.service.PermissionService;
  import com.example.service.RoleService;
  import com.example.service.UserService;
  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.util.StringUtils;

  import javax.annotation.Resource;
  import java.util.*;
  @Override
  protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
    String username  =(String) getAvailablePrincipal(principals);
    User user = userService.selectByUserName(username);
    //查询用户对应的角色信息
    List<Role> roleList=roleService.selectRoleList(user.getUid());
    SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();

    //系统角色
    //        Set<String> roles=new HashSet<>();
    //        //角色所用户的权限
    //        Set<String> permissions=new HashSet<>();
    for(Role role:roleList){
        info.addRole(role.getRname());
    //            roles.add(role.getRname());
        List<Permission> permissionList=permissionService.selectPermissionList(role.getRid());
        for(Permission permission:permissionList){
            info.addStringPermission(permission.getPname());
     //                permissions.add(permission.getPname());
        }
    //            info.setRoles(roles);
    //            info.setStringPermissions(permissions);
    }



   //        String username  =(String) getAvailablePrincipal(principals);
   //        //系统角色
   //        Set<String> roles=new HashSet<>();
   //        roles.add("超级管理员");
   //        //角色所用户的权限
   //        Set<String> permissions=new HashSet<>();
   //        //这里定义了一个list的权限,这个可以不一定要这样写,只要跟后面再controller中的注解一致即可
   //        permissions.add("admin:shiro:list");
   //        //为当前用户添加角色和权限
   //        SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
   //        info.setRoles(roles);
   //        info.setStringPermissions(permissions);

    return info;
}

doGetAuthenticationInfo:该方法用于校验当前登录请求的账号和密码是否正确;

   @Override
   protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
    //方法1:获取登陆人账号
    String name = token.getPrincipal().toString();
    //这里强转的类型不一定要是UsernamePasswordToken ,具体要看你在登录接口中所传的对象类型
    //方法2:获取登陆人账号
    UsernamePasswordToken usernamePasswordToken=  (UsernamePasswordToken)token;
    String username = usernamePasswordToken.getUsername();
    //判断内容是否为空
    User user=userService.selectByUserName(username);
    if(user==null){
        throw new AccountException("用户名不能为空");
    }
    //这里有三个参数,第一个是账号,第二个是密码,第三个是用户名
    //这里的密码需要传递用户的正确密码,这样shiro才能帮我们做校验
    SimpleAuthenticationInfo simpleAuthenticationInfo=new SimpleAuthenticationInfo(username,user.getUpwd(),getName());

    return simpleAuthenticationInfo;
   }

3:将我们自定义的realm和securityManager加入到spring容器中

  import com.example.realm.LoginAuthorizingRealm;
  import org.apache.shiro.mgt.SecurityManager;
  import org.apache.shiro.realm.Realm;
  import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
  import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
  import org.springframework.context.annotation.Bean;
  import org.springframework.context.annotation.Configuration;

  import java.util.LinkedHashMap;
  import java.util.Map;
  @Configuration
  public class ShiroConfig {
  //配置realm
  @Bean
  public Realm realm(){
    return  new LoginAuthorizingRealm();
  }
  @Bean
  public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager){
    ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean();
    shiroFilterFactoryBean.setSecurityManager(securityManager);
    //过滤器规则
    Map<String,String> filterChainDefinitionMap=new LinkedHashMap<>();
    filterChainDefinitionMap.put("/admin/login","anon");
    filterChainDefinitionMap.put("/admin/unAuth","anon");
    filterChainDefinitionMap.put("/admin/401","anon");
    filterChainDefinitionMap.put("/**","authc");
	//这里定义用户未认证时跳转的路径
    shiroFilterFactoryBean.setLoginUrl("/admin/401");
    //这里是用户登录成功后跳转的路径
    shiroFilterFactoryBean.setSuccessUrl("/admin/index");
    //这里是用户没有访问权限跳转的路径
    shiroFilterFactoryBean.setUnauthorizedUrl("/admin/unAuth");
    shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
    return shiroFilterFactoryBean;
 }
  //    将realm加入管理器中
  @Bean(name="securityManager")
   public DefaultWebSecurityManager defaultWebSecurityManager(){
    DefaultWebSecurityManager defaultWebSecurityManager=new DefaultWebSecurityManager();
    defaultWebSecurityManager.setRealm(realm());
    return defaultWebSecurityManager;
 }


  }

4编写controller代码

   package com.example.controller;

 import org.apache.shiro.SecurityUtils;
 import org.apache.shiro.authc.AccountException;
 import org.apache.shiro.authc.IncorrectCredentialsException;
 import org.apache.shiro.authc.UnknownAccountException;
 import org.apache.shiro.authc.UsernamePasswordToken;
 import org.apache.shiro.authz.annotation.RequiresPermissions;
 import org.apache.shiro.subject.Subject;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;

 @RestController
 @RequestMapping("admin/")
 public class ShiroController {
 @RequestMapping("login")
 public String login(String username, String password) {
    //获取主体
    Subject subject = SecurityUtils.getSubject();
    try {
        subject.login(new UsernamePasswordToken(username, password));
    } catch (UnknownAccountException e) {
        return "账号不存在";
    } catch (AccountException e) {
        return "账号或密码不正确";
    } catch (IncorrectCredentialsException e) {
        return "账号或密码不正确";
    }
     return "登陆成功";
  }

  @RequestMapping("401")
  public String toLogin() {
     return "401页面,您先去登陆吧!";
  }

  @RequestMapping("index")
  public String index() {
     return "index主页";
  }

  @RequiresPermissions("book:list")
  @RequestMapping("list")
  public String list() {
     return "book:list";
  }

  @RequiresPermissions("book:add")
  @RequestMapping("add")
  public String add() {
     return "book:add";
  }

  @RequiresPermissions("book:update")
  @RequestMapping("update")
  public String update() {
     return "book:update";
  }

  @RequiresPermissions("book:delete")
  @RequestMapping("delete")
  public String delete() {
     return "book:delete";
  }

   @RequiresPermissions("user:list")
   @RequestMapping("ulist")
   public String ulist() {
      return "user:list";
   }

   @RequiresPermissions("user:add")
   @RequestMapping("uadd")
   public String uadd() {
      return "user:add";
   }
   @RequestMapping("unAuth")
   public String unAuth() {
      return "未认证";
   }

 }

5新增exception,对于报AuthorizationException异常进行处理

 import org.apache.shiro.authz.AuthorizationException;
 import org.springframework.web.bind.annotation.ControllerAdvice;
 import org.springframework.web.bind.annotation.ExceptionHandler;
 import org.springframework.web.bind.annotation.ResponseBody;

 @ControllerAdvice
 public class ShiroExceptionHandle {
 @ExceptionHandler(AuthorizationException.class)
 @ResponseBody
     public String unAuth(AuthorizationException e){
        return "noAuth:"+e.getMessage();
     }
}
⚠️ **GitHub.com Fallback** ⚠️