springboot基于自定义注解的权限配置AOP+鉴权

WebMvcConfiguration.java

package com.fii.cms.web.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.format.datetime.DateFormatter;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;

import javax.annotation.Nullable;

@Configuration
public class WebMvcConfiguration extends WebMvcConfigurationSupport {

    @Value("${swagger.enable}")
    private boolean swaggerEnabled;

    @Override
    protected void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowCredentials(true)
                .allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE")
                .allowedHeaders("*")
                .maxAge(3600);
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        if (swaggerEnabled) {
            registry.addResourceHandler("/doc.html")
                    .addResourceLocations("classpath:/META-INF/resources/");
            registry.addResourceHandler("/webjars/**")
                    .addResourceLocations("classpath:/META-INF/resources/webjars/");
        }
        registry.addResourceHandler("/static/**")
                .addResourceLocations("classpath:/static/");
        super.addResourceHandlers(registry);
    }


    /**
     * 格式化
     *
     * @param registry
     */
    public void addFormatters(FormatterRegistry registry) {
        registry.addFormatter(new DateFormatter("yyyy-MM-dd HH:mm:ss"));
    }

    /**
     * 添加拦截器
     *
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        super.addInterceptors(registry);
        // 添加一个拦截器,检查会话,URL以admin开头的都使用此拦截器
//        registry.addInterceptor(sessionInterceptor).addPathPatterns("/admin/**");
    }

    @Bean
    @Nullable
    public TaskScheduler taskScheduler() {
        ThreadPoolTaskScheduler threadPoolScheduler = new ThreadPoolTaskScheduler();
        threadPoolScheduler.setThreadNamePrefix("SockJS-");
        threadPoolScheduler.setPoolSize(Runtime.getRuntime().availableProcessors());
        threadPoolScheduler.setRemoveOnCancelPolicy(true);
        return threadPoolScheduler;
    }
}

aop.AuthVerifyAOP.java

package com.fii.cms.web.aop;

import com.fii.cms.core.annotation.AuthApis;
import com.fii.cms.core.api.ApiAuthVerify;
import com.fii.cms.core.exception.GlobalException;
import com.fii.cms.core.pojo.vo.app.LocalAppResourceInfo;
import com.fii.cms.core.pojo.vo.user.UserInfoVo;
import com.fii.cms.core.pojo.vo.user.UserParam;
import com.fii.cms.core.resultBody.ResultCode;
import com.fii.cms.user.common.AuthenticationFacade;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Aspect
@Component
public class AuthVerifyAop {

    @Value("${oauth.user_cache_key}")
    private String userCacheKey;

    @Autowired
    private AuthenticationFacade facade;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Pointcut("@annotation( com.fii.cms.core.annotation.AuthApis)")
    public void doOperation() {
    }

    @Before("doOperation()&&@annotation(authApis)")
    public void before(JoinPoint point, AuthApis authApis) throws GlobalException {
        //获取请求路由
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        assert requestAttributes != null;
        HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
        String requestURI = request.getRequestURI();
        //获取去用户信息
        String account = facade.getCurrentUserName();
        UserInfoVo userInfoVo = (UserInfoVo) redisTemplate.opsForHash().get(userCacheKey, account);
        if (userInfoVo == null)
            throw new GlobalException(ResultCode.USER_NOT_LOGIN);
        //获取用户本系统权限信息
        List<LocalAppResourceInfo> localRes = userInfoVo.getLocalRes();
        if (localRes != null && localRes.size() > 0) {
            List<String> collect = localRes.stream().map(LocalAppResourceInfo::getResourceId).collect(Collectors.toList());
            //通过注解获取被访问接口可允许的权限ID
            String[] value = authApis.value();
            if (value.length == 0)
                //通过路由获取被访问接口可允许的权限ID
                value = ApiAuthVerify.getResourceIds(requestURI);
            if (value == null || value.length == 0)
                throw new GlobalException(ResultCode.PERMISSION_NOT_ALLOW);

            //特殊角色权限认证
            Object[] args = point.getArgs();
            if (!special(args, collect, requestURI))
                throw new GlobalException(ResultCode.PERMISSION_NOT_ALLOW);

            //权限认证
            for (String resource : value) {
                if (collect.contains(resource))
                    return;
            }

        }
        throw new GlobalException(ResultCode.PERMISSION_NOT_ALLOW);
    }

    private boolean special(Object[] args, List<String> collect, String requestURI) {
        //角色编辑接口:接口多用权限处理-根据参数判断接口对应的按钮功能
        if (Objects.equals(ApiAuthVerify.SYS_ROLE_ENABLE.getUri(), requestURI)) {
            String roleName = Objects.isNull(args[1]) ? "" : (String) args[1];
            Integer status = Objects.isNull(args[2]) ? null : (Integer) args[2];
            String[] resourceIds = ApiAuthVerify.SYS_ROLE_ENABLE.getResourceIds();
            if (!StringUtils.isEmpty(roleName)) {
                return collect.contains(resourceIds[0]);
            }
            if (status == null) {
                return collect.contains(resourceIds[1]);
            }
        }
        //用户查询接口多用权限认证
        if (Objects.equals(ApiAuthVerify.SYS_USER_M.getUri(), requestURI)) {
            UserParam userParams = (UserParam) args[0];
            String[] resourceIds = ApiAuthVerify.SYS_USER_M.getResourceIds();
            //查询角色用户列表
            if (StringUtils.isNotEmpty(userParams.getRoleId())) {
                return collect.contains(resourceIds[1]);
            } else {
                if (StringUtils.isNotEmpty(userParams.getOrganizeId())) {
                    if (collect.contains(resourceIds[2]))
                        return true;
                    else
                        return collect.contains(resourceIds[0]);
                }
                return collect.contains(resourceIds[0]);
            }
        }
        return true;
    }
}

AuthApis.java

package com.fii.cms.core.annotation;

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Documented
public @interface AuthApis {
    String[] value() default {};
    String desc()  default "";
}

 ApiAuthVerify.java

package com.fii.cms.core.api;

import java.util.Objects;

public enum ApiAuthVerify {

    /**用户管理*/
    SYS_USER_M("/oauth/user/list", new String[]{"SYS-USER-M","SYS-ROLE-USER","SYS-ORG-USER"}),
    SYS_USER_ENABLE("/oauth/user/status", new String[]{"SYS-USER-ENABLE"}),
    SYS_USER_EDIT("/oauth/update/user", new String[]{"SYS-USER-EDIT"}),
    SYS_USER_RESETPSW("/oauth/reset/password", new String[]{"SYS-USER-RESETPSW"}),
    SYS_USER_IMPORT("/oauth/user/upload", new String[]{"SYS-USER-IMPORT"}),
    SYS_USER_ADD("/oauth/add/user", new String[]{"SYS-USER-ADD"}),
    SYS_USER_CHANGEROLE("/role/add/user/roles", new String[]{"SYS-USER-CHANGEROLE", "SYS-USER-ASSIGNROLE"}),
    SYS_USER_CHANGEORGANIZE("/organize/add/user/organizes", new String[]{"SYS-USER-CHANGEORGANIZE"}),
    SYS_USER_LOOKAUTH("/auth/user/list", new String[]{"SYS-AUTH-M","SYS-USER-LOOKAUTH"}),
    SYS_USER_PERMISSION("/auth/distribution", new String[]{"SYS-AUTH-M","SYS-USER-PERMISSION"}),
    /**角色管理*/
    SYS_ROLE_M("/role/role/list",new String[]{"SYS-ROLE-M"}),
    SYS_ROLE_ADD("/role/add",new String[]{"SYS-ROLE-ADD"}),
    SYS_ROLE_DELETE("/role/delete",new String[]{"SYS-ROLE-DELETE"}),
    SYS_ROLE_ENABLE("/role/edit",new String[]{"SYS-ROLE-EDIT","SYS-ROLE-ENABLE"}),
    SYS_ROLE_ADD_USER("/role/add/role/user",new String[]{"SYS-ROLE-ADD-USER"}),
    SYS_ROLE_DELETE_USER("/role/delete/role/user",new String[]{"SYS-ROLE-DELETE-USER"}),
//    SYS_ROLE_AUTH("",new String[]{"SYS-ROLE-AUTH"}),
    /**组织管理*/
    SYS_ORG_M("/organize/list/info",new String[]{"SYS-ORG-M"}),
    SYS_ORG_ENABLE("/organize/disable",new String[]{"SYS-ORG-ENABLE"}),
    SYS_ORG_EDIT("/organize/edit",new String[]{"SYS-ORG-EDIT"}),
    SYS_ORG_DELETE_USER("/organize/delete/users",new String[]{"SYS-ORG-DELETE-USER"}),
    SYS_ORG_DELETE("/organize/delete",new String[]{"SYS-ORG-DELETE"}),
    SYS_ORG_ADD_USER("/organize/add/users",new String[]{"SYS-ORG-ADD-USER"}),
    SYS_ORG_ADD("/organize/add",new String[]{"SYS-ORG-ADD"}),
    /**权限管理*/
    SYS_AUTH_APP("/auth/app/list",new String[]{"SYS-AUTH-M"}),
    SYS_AUTH_ADD("/auth/add/point",new String[]{"SYS-AUTH-M"}),
    SYS_AUTH_DELETE("/auth/remove/point",new String[]{"SYS-AUTH-M"}),
    SYS_AUTH_EDIT("/auth/edit/point",new String[]{"SYS-AUTH-M"}),
    SYS_AUTH_APP_POINTS("/auth/all/point/list",new String[]{"SYS-AUTH-M"}),
    SYS_AUTH_POINT_RESOURCE("/auth/point/list",new String[]{"SYS-AUTH-M"}),
    SYS_AUTH_ENABLE("/auth/enable/point",new String[]{"SYS-AUTH-M"}),
    SYS_AUTH_ROLE_OR_USER("/auth/resource/distribution/list",new String[]{"SYS-AUTH-M"}),
    SYS_AUTH_ROLE_OR_USER_POINT("/auth/resource/detail",new String[]{"SYS-ROLE-AUTH","SYS-ROLE-AUTH","SYS-USER-PERMISSION"}),
    SYS_AUTH_CANCEL("/auth/user/invalid",new String[]{"SYS-AUTH-M"}),
    SYS_AUTH_IMPORT("/auth/auth/upload",new String[]{"SYS-AUTH-M"}),
    SYS_AUTH_EXPORT("/auth/auth/download",new String[]{"SYS-AUTH-M"}),
    /**权限管理*/
    SYS_APP_REGISTER("/client/add/app",new String[]{"SYS-APP-R","SYS-APP-M"}),
    SYS_APP_LIST("/client/app/list",new String[]{"SYS-APP-R","SYS-APP-M"}),
    SYS_APP_EDIT("/client/app/edit",new String[]{"SYS-APP-R","SYS-APP-M"}),
    SYS_APP_DELETE("/client/app/delete",new String[]{"SYS-APP-R","SYS-APP-M"}),
    /**消息管理**/
    SYS_MESSAGE_HISTORY("/message/history/list",new String[]{"SYS-MESSAGE-HISTORY"})
    ;
    private String uri;
    private String[] resourceIds;

    ApiAuthVerify(String uri, String[] resourceIds) {
        this.uri = uri;
        this.resourceIds = resourceIds;
    }

    public static String[] getResourceIds(String uri) {
        for (ApiAuthVerify verify : ApiAuthVerify.values()) {
            if (Objects.equals(verify.uri, uri))
                return verify.resourceIds;
        }
        return null;
    }

    public String getUri() {
        return uri;
    }

    public String[] getResourceIds() {
        return resourceIds;
    }
}

AuthenticationFacade.java

package com.fii.cms.user.common;

import com.fii.cms.core.exception.GlobalException;
import com.fii.cms.core.resultBody.ResultCode;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.List;


@Component
public class AuthenticationFacade {

    public Authentication getAuthentication() {
        return SecurityContextHolder.getContext().getAuthentication();
    }

    public String getCurrentUserName() {
        Object o = getAuthentication().getPrincipal();
        String username = "";
        if (o instanceof User)
            username = ((User) o).getUsername();
        if (o instanceof String) {
            username = (String) o;
        }
        return username;
    }

    public void verifyLogin(){
        String currentUserName = getCurrentUserName();
        if (StringUtils.isEmpty(currentUserName))
            throw new GlobalException(ResultCode.USER_NOT_LOGIN);
    }

    public boolean verifyAuthen(String role){
        List<GrantedAuthority> grantedAuthorities = AuthorityUtils.commaSeparatedStringToAuthorityList(role);
        return getAuthentication().getAuthorities().contains(grantedAuthorities.get(0));
    }

    public boolean verifySuperAuthen(){
        return verifyAuthen("ROLE_ADMIN");
    }
}

OauthController.java

package com.fii.cms.user.controller;

import com.fii.cms.core.annotation.AuthApis;
import com.fii.cms.core.pojo.vo.user.*;
import com.fii.cms.core.resultBody.PageBody;
import com.fii.cms.core.resultBody.ResultBody;
import com.fii.cms.user.service.UserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

@Api(tags = "oauth用户相关")
@RequestMapping("oauth")
@RestController
public class OauthUserController {

    @Autowired
    private UserService userService;

    @ApiOperation(value = "获取当前用户信息", httpMethod = "GET")
    @RequestMapping("/current/user")
    public ResultBody<UserInfoVo> getCurrentUserInfo() {
        return ResultBody.success(userService.getCurrentUserInfo());
    }

    @ApiOperation(value = "获取指定用户信息", httpMethod = "GET")
    @RequestMapping("/user")
    public ResultBody<UserInfoVo> getUserInfo(@ApiParam(value = "用户ID", required = true) @RequestParam String userId) {
        return userService.getUserInfo(userId);
    }

    @ApiOperation(value = "获取简单用户信息", httpMethod = "GET")
    @RequestMapping("/user/simple")
    public ResultBody<List<UserSimpleInfoVo>> getUserSimpleInfo(@ApiParam(value = "用户工号/姓名") @RequestParam(required = false) String account) {
        return userService.getUserSimpleInfo(account);
    }

    @AuthApis
    @ApiOperation(value = "获取用户信息列表", httpMethod = "POST")
    @PostMapping("/user/list")
    public ResultBody<PageBody<List<UserInfoVo>>> getUserInfoList(@ApiParam(value = "用户信息") @RequestBody(required = false) UserParam userParam) {
        return userService.getUserInfoList(userParam);
    }

    @AuthApis
    @ApiOperation(value = "添加用户信息用户信息", httpMethod = "POST")
    @PostMapping("/add/user")
    public ResultBody addUser(@ApiParam(value = "用户信息") @Validated @RequestBody AddUserVo addUserVo) {
        return userService.addUser(addUserVo);
    }

    @AuthApis
    @ApiOperation(value = "修改用户信息用户信息", httpMethod = "POST")
    @PostMapping("/update/user")
    public ResultBody updateUser(@ApiParam(value = "用户信息") @Validated @RequestBody AddUserVo addUserVo) {
        return userService.updateUser(addUserVo);
    }

    @ApiOperation(value = "修改个人用户信息用户信息", httpMethod = "POST")
    @PostMapping("/update/personal")
    public ResultBody updatePersonal(@ApiParam(value = "用户信息") @Validated @RequestBody UserPersonalVo addUserVo) {
        return userService.updatePersonal(addUserVo);
    }

    @AuthApis
    @ApiOperation(value = "禁用用户", httpMethod = "POST")
    @PostMapping("/user/status")
    public ResultBody editUserStatus(@ApiParam(value = "用户Id:多个用英文逗号隔开") @RequestParam String userId,
                                     @ApiParam(value = "启用状态:0为启用,1为未启用") @RequestParam Integer status) {
        return userService.editUserStatus(userId, status);
    }

    @AuthApis
    @ApiOperation(value = "重置密码", httpMethod = "POST")
    @PostMapping("/reset/password")
    public ResultBody resetPassword(@ApiParam(value = "用户Id") @RequestParam String userId,
                                    @ApiParam(value = "密码") @RequestParam String password) {
        return userService.resetPassword(userId, password);
    }

    @ApiOperation(value = "修改密码", httpMethod = "POST")
    @PostMapping("/edit/password")
    public ResultBody editPassword(@ApiParam(value = "用户Id",required = true) @RequestParam String userId,
                                   @ApiParam(value = "旧密码",required = true) @RequestParam String oldPassword,
                                   @ApiParam(value = "新密码",required = true) @RequestParam String newPassword) {
        return userService.editPassword(userId, oldPassword, newPassword);
    }

//    @ApiOperation(value = "发送验证码", httpMethod = "POST")
//    @PostMapping("/send/code")
//    public ResultBody sendCode(@ApiParam(value = "用户工号") @RequestParam String account,
//                               HttpServletRequest request) {
//        return userService.sendCode(account, request);
//    }

    @ApiOperation(value = "忘记密码", httpMethod = "POST")
    @PostMapping("/forget/password")
    public ResultBody forgetPassword(@ApiParam(value = "用户工号") @RequestParam String account,
                                     @ApiParam(value = "验证码") @RequestParam String code,
                                     @ApiParam(value = "新密码") @RequestParam String passwordNew,
                                     HttpServletRequest request) {
        return userService.forgetPassword(account, code, passwordNew, request);
    }

    @ApiOperation(value = "登录", httpMethod = "POST")
    @PostMapping("/login")
    public ResultBody login() {
        return ResultBody.success();
    }

    @ApiOperation(value = "登出", httpMethod = "GET")
    @GetMapping("/logout")
    public ResultBody logout(HttpServletRequest request) {
        return userService.logout(request);
    }

    @ApiOperation(value = "服务端登录获取token", httpMethod = "GET")
    @GetMapping("get/token")
    public ResultBody getToken() {
        return ResultBody.success(userService.getToken());
    }

//    @ApiOperation(value = "使token失效", httpMethod = "GET")
//    @GetMapping("/revokeToken")
//    public ResultBody revokeToken(HttpServletRequest request) {
//        return userService.revokeToken(request);
//    }

    @ApiOperation(value = "用户导入模板下载", httpMethod = "GET")
    @GetMapping("download/template")
    public void downloadTemplate(HttpServletResponse response) {
        userService.downloadTemplate(response);
    }

    @AuthApis
    @ApiOperation(value = "用户批量上传", httpMethod = "POST")
    @PostMapping("user/upload")
    public ResultBody userUpload(@RequestParam("file") MultipartFile file) throws IOException {
        return userService.userUpload(file);
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值