spring boot +shiro+mybaits 多数据源项目搭建【二】shiro 整合


上一章:https://blog.csdn.net/qq_41780372/article/details/104823854 

一、修改生成的实体,创建查询用户信息的方法

1.一个用户是对应多个角色,一个角色对应多个权限(菜单)。
我们在用户实体上面新增一个角色集合 SysUser.java

  List<SysRole> roles;

在角色上面增加权限集合 SysRole.java

 List<SysMenu> sysMenus;

 记得两个属性上面均需要加上注解@TableField(exist = false),否则在查询数据库时mybaits-plus会把这个当做一个数据库字段进行查询。

2.新增加一个登陆的service,创建一个根据用户名查用户及所有角色和权限的方法。

SysLoginService.java内增加一个接口
SysUser getUserByName(String username);
SysLoginServiceImpl.java内实现接口
@Service
public class SysLoginServiceImpl implements SysLoginService {

    @Autowired
    private SysUserServiceImpl sysUserService;
    @Autowired
    private SysRoleServiceImpl sysRoleService;
    @Autowired
    private SysRoleMenuServiceImpl sysRoleMenuService;
    @Autowired
    private SysMenuServiceImpl sysMenuService;
    @Autowired
    private SysUserRoleServiceImpl sysUserRoleService;

    @Override
    public SysUser getUserByName(String username) {
        SysUser sysUser=sysUserService.getOne(new QueryWrapper<SysUser>().eq("username",username));
        if(sysUser!=null){
            List<SysUserRole> sysUserRoles=sysUserRoleService.list(new QueryWrapper<SysUserRole>().eq("user_id",sysUser.getUserId()));
            List<SysRole> sysRoles=new ArrayList<>();
            for(SysUserRole sysUserRole:sysUserRoles){
                SysRole sysRole=sysRoleService.getById(sysUserRole.getRoleId());
                List<SysMenu> sysMenuList=new ArrayList<>();
                List<SysRoleMenu> roleMenuList=sysRoleMenuService.list(new QueryWrapper<SysRoleMenu>().eq("role_id",sysUserRole.getRoleId()));
                for(SysRoleMenu sysRoleMenu:roleMenuList){
                    sysMenuList.add(sysMenuService.getById(sysRoleMenu.getMenuId()));
                }
                sysRole.setSysMenus(sysMenuList);
                sysRoles.add(sysRole);
            }
            sysUser.setRoles(sysRoles);
        }
        return sysUser;
    }
}

二、编辑shiro的配置。

编辑CustomRealm.java

package cn.mvapi.xiaobao.common.shiro;



import cn.mvapi.xiaobao.common.system.entity.SysMenu;
import cn.mvapi.xiaobao.common.system.entity.SysRole;
import cn.mvapi.xiaobao.common.system.entity.SysUser;
import cn.mvapi.xiaobao.common.system.service.SysUserService;
import cn.mvapi.xiaobao.common.system.service.impl.SysLoginServiceImpl;
import cn.mvapi.xiaobao.common.system.service.impl.SysUserServiceImpl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
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.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;


public class CustomRealm extends AuthorizingRealm {

    @Autowired
    private SysLoginServiceImpl sysLoginService;
    @Autowired
    private SysUserServiceImpl sysUserService;
    //进入角色授权 该方法是将用户的角色及权限全部查出来
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //获取登录用户名
        String username = (String) principalCollection.getPrimaryPrincipal();
        //根据用户名去数据库查询用户信息
        SysUser sysUser = sysLoginService.getUserByName(username);//new QueryWrapper<SysUser>().eq("username",username));
        //添加角色和权限
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        for (SysRole role : sysUser.getRoles()) {
            //添加角色
            simpleAuthorizationInfo.addRole(role.getRoleName());
            //添加权限
            for (SysMenu sysMenu : role.getSysMenus()) {
                if(sysMenu.getPerms()!=null&&!sysMenu.getPerms().trim().equals("")){
                    for(String str:sysMenu.getPerms().split(",")){
                        simpleAuthorizationInfo.addStringPermission(str);
                    }
                }
            }
        }
        return simpleAuthorizationInfo;
    }
    
    //主要用于账号密码校验,通过用户名查出数据库内的密码,交给shiro校验
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //加这一步的目的是在Post请求的时候会先进认证,然后在到请求
        if (authenticationToken.getPrincipal() == null) {
            return null;
        }
        //获取用户信息
        String name = authenticationToken.getPrincipal().toString();
        SysUser user =  sysUserService.getOne(new QueryWrapper<SysUser>().eq("username",name));

        if (user == null) {
            //这里返回后会报出对应异常
            return null;
        } else {
            //这里验证authenticationToken和simpleAuthenticationInfo的信息
            //用户名–此处传的是用户对象
            //密码—从数据库中获取的密码
            //getName() //当前的realm名
            SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(name, user.getPassword().toString(), getName());
            return simpleAuthenticationInfo;
        }
    }
}

 

shiro配置  ShiroConfig.java 
将上面的自定义realm添加到容器内,另外如果有多种校验方式可以添加多个realm。

配置拦截的路径和跳转条件。

package cn.mvapi.xiaobao.common.shiro;



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.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

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

@Configuration
public class ShiroConfig {
    //不加这个注解不生效,具体不详
    @Bean
    @ConditionalOnMissingBean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator defaultAAP = new DefaultAdvisorAutoProxyCreator();
        defaultAAP.setProxyTargetClass(true);
        return defaultAAP;
    }

    //将自己的验证方式加入容器
    @Bean
    public CustomRealm myShiroRealm() {
        CustomRealm customRealm = new CustomRealm();
        return customRealm;
    }

    //权限管理,配置主要是Realm的管理认证
    @Bean
    public SecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(myShiroRealm());
        return securityManager;
    }

    //Filter工厂,设置对应的过滤条件和跳转条件
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        Map<String, String> map = new HashMap<>();
        map.put("/test/**","anon");
        map.put("/public/**","anon");
        map.put("/plugin/**","anon");
        //登出
        map.put("/logout", "logout");
        //对所有用户认证
        map.put("/admin/**", "authc");
        map.put("/user/**", "authc");
        //登录
        shiroFilterFactoryBean.setLoginUrl("/login/index.html");
        //首页
        shiroFilterFactoryBean.setSuccessUrl("/index");
        //错误页面,认证不通过跳转
        shiroFilterFactoryBean.setUnauthorizedUrl("/login/index.html");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
        return shiroFilterFactoryBean;
    }

    //加入注解的使用,不加入这个注解不生效
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }
}

三、编辑登录功能,测试功能是否正常。

1.编辑通用的数据返回实体。ReturnData.java
会使用枚举的话这里也可以用上。

public class ReturnData {
    private int code;
    private String msg;
    private Object date;

    public ReturnData() {

    }

    public ReturnData(int code, String msg, Object date) {
        this.code = code;
        this.msg = msg;
        this.date = date;
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public Object getDate() {
        return date;
    }

    public void setDate(Object date) {
        this.date = date;
    }
}

编辑登录控制器及相应的权限测试方法。SysLoginController.java

package cn.mvapi.xiaobao.common.system.controller;


import cn.mvapi.xiaobao.common.system.entity.ReturnData;
import cn.mvapi.xiaobao.common.system.entity.SysUser;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
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;

//import com.sun.jndi.toolkit.url.UrlUtil;
//import org.apache.commons.codec.net.URLCodec;

@Controller
public class SysLoginController {
    @ResponseBody
    @RequestMapping("/login")
    public ReturnData login(SysUser user) {
        //添加用户认证信息
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(
                user.getUsername(),
                user.getPassword()
        );
        String error="";
        try {
            //进行验证,这里可以捕获异常,然后返回对应信息
            subject.login(usernamePasswordToken);
//            subject.checkRole("admin");
 //           subject.checkPermissions("query", "add");
        } catch (AuthenticationException e) {
            //e.printStackTrace();
           // return "账号或密码错误!";
           return new ReturnData(201,"账号或密码错误!",null);
        } catch (AuthorizationException e) {
           // e.printStackTrace();
            return new ReturnData(202,"您没有权限!",null);
            // return "没有权限";
        }
        return new ReturnData(200,"登录成功!",null);
    }
    //注解验角色和权限
    @RequiresPermissions("sys:role:delete")
    @RequestMapping("/delete")
    @ResponseBody
    public String index() {
        return "delete";
    }


    @RequiresPermissions("sys:user:save")
    @RequestMapping("/save")
    @ResponseBody
    public String save() {
        return "save";
    }

    //@RequiresPermissions("sys:user:save")
    @RequiresRoles("管理员")
    @RequestMapping("/role")
    @ResponseBody
    public String role() {
        return "role";
    }

    @RequiresPermissions("sys:role:otherpermission")
    @RequestMapping("/otherPermission")
    @ResponseBody
    public String others() {
        return "用户不存在的权限";
    }

    @RequiresRoles("otherRoles")
    @RequestMapping("/otherRoles")
    @ResponseBody
    public String otherRoles() {
        return "用户不存在的角色";
    }
}

启动项目测试功能是否正常。
未登录情况下访问这里会抛出错误http://localhost:8081/save 
 

访问登录接口:http://localhost:8081/login/?username=admin&password=123 

提示登录成功后再次访问上面接口 ,界面显示save代表正常。
访问http://localhost:8081/otherPermission

http://localhost:8081/otherRoles 系统会抛出错误,因为当前用户没有这个角色和权限。

本次教程结束! 

上一章:https://blog.csdn.net/qq_41780372/article/details/104823854

下一章:https://blog.csdn.net/qq_41780372/article/details/105096733

github地址:https://github.com/xiaobaos/springboot

码云地址:https://gitee.com/xiaobaomeat/springboot

 

项目优先更新到github上面。
下一章:引入界面。 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章