SpringBoot整合shiro

导入依赖

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

配置安全管理器

/**
 * @Description:shiro配置
 * @author Chen
 * @create 2019-07-07 20:02
 */
@Configuration
public class ShiroConfig {
    /**
     * 创建ShiroFilterFactoryBean
     */
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager){
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        //设置安全管理器
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        // setLoginUrl 如果不设置值,默认会自动寻找Web工程根目录下的"/login.jsp"页面 或 "/login" 映射
        shiroFilterFactoryBean.setLoginUrl("/notLogin");
        //添加Shiro内置过滤器
        /**
         * Shiro内置过滤器,可以实现权限相关的拦截器
         *    常用的过滤器:
         *       anon: 无需认证(登录)可以访问
         *       authc: 必须认证才可以访问
         *       user: 如果使用rememberMe的功能可以直接访问
         *       perms: 该资源必须得到资源权限才可以访问
         *       role: 该资源必须得到角色权限才可以访问
         */
        Map<String,String> map = new LinkedHashMap<String, String>();
        map.put("/adminLogin","anon");
        map.put("/swagger-ui.html", "anon");
        map.put("/swagger-resources", "anon");
        map.put("/v2/api-docs", "anon");
        map.put("/webjars/springfox-swagger-ui/**", "anon");
        map.put("/*","authc");

        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
        return shiroFilterFactoryBean;
    }

    /**
     * 创建DefaultWebSecurityManager
     * @return
     */
    @Bean("securityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager(){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //关联UserRealm
        securityManager.setRealm(getUserRealm());
        return securityManager;
    }

    /**
     * 创建realm
     * @return
     */
    @Bean("userRealm")
    public UserRealm getUserRealm(){
        return new UserRealm();
    }

    @Bean(name="lifecycleBeanPostProcessor")
    public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    /**
     * 开启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() {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(getDefaultWebSecurityManager());
        return authorizationAttributeSourceAdvisor;
    }
}

配置Realm

/**
 * @Description:Realm配置
 * @author Chen
 * @create 2019-07-07 20:02
 */
public class UserRealm extends AuthorizingRealm {
    @Autowired
    private IUserService userService;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("执行授权");
        String uEmail = (String) principalCollection.getPrimaryPrincipal();
        User user = userService.getByEmail(uEmail);
        List<String> permissions = new ArrayList<String>();
        List<String> roles = new ArrayList<String>();

        if ("admin".equals(uEmail)) {
            //让超级管理员拥有所有权限
            permissions.add("*:*");
        } else {
            //根据用户ID查询该用户具有的角色
            roles = userService.getRoleByUserId(user.getuId());
            //根据用户ID查询该用户具有的权限
            permissions = userService.getPermissionByUserId(user.getuId());
            if (permissions.get(0) == null){
                throw new MyException(400,"无权限");
            }
        }
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.addStringPermissions(permissions);
        info.addRoles(roles);
        return info;
    }


    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("··········执行认证逻辑··········");
        //转为UsernamePasswordToken
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        User user = userService.getByEmail(token.getUsername());
        //判断用户名
        if (user == null) {
            //用户名不存在
            //Shiro底层会抛出异常
            return null;
        }
        //判断密码
        return new SimpleAuthenticationInfo(user.getuEmail(), user.getuPassword(), "");
    }
}

认证

@PostMapping("/adminLogin")
public Responsive adminLogin(@RequestBody AdminLoginReq adminLoginReq) {
    //1.获取subject
    Subject subject = SecurityUtils.getSubject();
    //2.封装用户数据
    UsernamePasswordToken token = new UsernamePasswordToken(adminLoginReq.getUEmail(), adminLoginReq.getUPassword());
    //3.执行登录方法
    try {
        subject.login(token);
        //登录成功
        return Responsive.success();
    } catch (UnknownAccountException e) {
        //用户名不存在
        return Responsive.of(400, "用户名或密码错误");
    } catch (IncorrectCredentialsException e) {
        //密码错误
        return Responsive.of(400, "用户名或密码错误");
    }
}

授权

使用注解即可实现权限控制:

  • @RequiresPermissions("需要的权限")
  • @RequiresRoles("需要的角色")
  • @PermissionName(“自定义注解用于获取权限名称信息”)

加载权限到数据库:

/**
 * @author Chen
 * @Description 自定义注解  用于获取权限名称
 * @create 2019-07-08 13:13
 */
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface PermissionName {
    String value();
}
/**
 * @author Chen
 * @Description
 * @create 2019-07-08 13:14
 */
@Api(tags = "权限模块")
@Controller
public class PermissionController {


    @Autowired
    private IPermission permissionService;

    //请求映射处理映射器
    //springmvc在启动时候将所有贴有请求映射标签:RequestMapper方法收集起来封装到该对象中
    @Autowired
    private RequestMappingHandlerMapping rmhm;


    @ResponseBody
    @GetMapping("reload")
    public Map<String,Object> reload(){
        Map<String,Object> map = new HashMap<String, Object>();
        //将系统中所有权限表达式加载进入数据库
        //0:从数据库中查询出所有权限表达式,然后对比,如果已经存在了,跳过,不存在添加
        List<String> resourcesList = permissionService.getAllResource();
        //1:获取controller中所有带有@RequestMapper标签的方法
        Map<RequestMappingInfo, HandlerMethod> handlerMethods = rmhm.getHandlerMethods();
        Collection<HandlerMethod> methods = handlerMethods.values();
        for (HandlerMethod method : methods) {
            //2:遍历所有方法,判断当前方法是否贴有@RequiresPermissions权限控制标签
            RequiresPermissions anno = method.getMethodAnnotation(RequiresPermissions.class);
            if(anno != null){
                //3:如果有,解析得到权限表达式,封装成Permission对象保存到Permission表中
                //权限表达式
                String resource = anno.value()[0];

                //去除重复的
                if(resourcesList.contains(resource)){
                    continue;
                }
                Permission p = new Permission();
                p.setResource(resource);
                p.setCreateTime(new Date());
                //设置权限名称
                p.setName(method.getMethodAnnotation(PermissionName.class).value());
                //保存
                permissionService.addPermission(p);
            }
        }

        map.put("type","success");
        map.put("msg","加载成功!");
        return map;
    }
}

异常的处理

/**
 * @author Chen
 * @Description 全局异常处理
 * @create 2019-07-08 13:14
 */
@ControllerAdvice
public class GlobalExceptionHandler {

    /**
     * @Author
     * 处理自定义异常
     **/
    @ExceptionHandler(MyException.class)
    @ResponseBody
    public Map<String,Object> handlerMyException(MyException exception){
        Map<String,Object> map = new HashMap<>();
        map.put("errorCode", exception.getStatus());
        map.put("errorMsg", exception.getMessage());
        return map;
    }

    /**
     * 权限异常
     * @param request
     * @param response
     * @return
     */
    @ResponseBody
    @ExceptionHandler(UnauthorizedException.class)
    public Responsive authorizationException(HttpServletRequest request, HttpServletResponse response) {
        return Responsive.of(400,"无权限");
    }


    /**
     * @Description 处理未知异常
     **/
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public Map<String,Object> handlerException(Exception exception){
        Map<String,Object> map = new HashMap<>();
        map.put("errorCode", 500);
        map.put("errorMsg", "未知错误");
        return map;
    }
}

转载于:https://www.cnblogs.com/chen88/p/11538365.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值