SpringBoot Security JWT 登錄授權認證

SpringBoot2.X Security JWT 登錄授權認證

目前在java后端的開發(fā)項目中,授權認證這個功能基本是必備的,這里只講常用的登錄授權認證,Spring Security + JWT(java web token)。
Spring Security 官網(wǎng)介紹
https://spring.io/projects/spring-security

image.png

官網(wǎng)文檔說明:
https://docs.spring.io/spring-security/site/docs/5.4.1/reference/html5/
image.png

SpringSecurity是一個強大的可高度定制的認證和授權框架,
對于Spring應用來說它是一套Web安全標準。SpringSecurity注重于為Java應用提供認證和授權功能,
像所有的Spring項目一樣,它對自定義需求具有強大的擴展性。

JWT是JSON WEB TOKEN的縮寫,它是基于 RFC 7519 標準定義的一種可以安全傳輸?shù)牡腏SON對象,
由于使用了數(shù)字簽名,所以是可信任和安全的。

JWT的組成
JWT token的格式:header.payload.signature
1.header中用于存放簽名的生成算法 {"alg": "HS512"}

2.payload中用于存放用戶名、token的生成時間和過期時間
{"sub":"admin","created":1489079981393,"exp":1489684781}

3.signature為以header和payload生成的簽名,一旦header和payload被篡改,驗證將失敗
//secret為加密算法的密鑰
String signature = HMACSHA512(base64UrlEncode(header) + "." +base64UrlEncode(payload),secret)

直接上案例:

gihub 代碼地址:https://github.com/LaiHouWen/SpringSecurityJwt

項目借鑒 開源項目 mall商城,http://www.macrozheng.com/#/architect/mall_arch_04,剝離出來的。

先準備一張用戶表admin,角色表role,用戶權限表permission,用戶和角色關系表,用戶與角色是多對多關系admin_role_relation,用戶角色和權限關系表,角色與權限是多對多關系role_permission_relation,用戶和權限關系表admin_permission_relation。

admin表sql

DROP TABLE IF EXISTS `admin`;
CREATE TABLE `admin`  (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `username` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `password` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `email` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '郵箱',
  `nick_name` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '昵稱',
  `create_time` datetime(0) NULL DEFAULT NULL COMMENT '創(chuàng)建時間',
  `login_time` datetime(0) NULL DEFAULT NULL COMMENT '最后登錄時間',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用戶表' ROW_FORMAT = Dynamic;

role表SQL

DROP TABLE IF EXISTS `role`;
CREATE TABLE `role`  (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '名稱',
  `description` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '描述',
  `admin_count` int(11) NULL DEFAULT NULL COMMENT '后臺用戶數(shù)量',
  `create_time` datetime(0) NULL DEFAULT NULL COMMENT '創(chuàng)建時間'
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用戶角色表' ROW_FORMAT = Dynamic;

permission表sql

DROP TABLE IF EXISTS `permission`;
CREATE TABLE `permission`  (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `pid` bigint(20) NULL DEFAULT NULL COMMENT '父級權限id',
  `name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '名稱',
  `value` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '權限值',
  `create_time` datetime(0) NULL DEFAULT NULL COMMENT '創(chuàng)建時間'
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 19 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用戶權限表' ROW_FORMAT = Dynamic;

admin_permission_relation表sql

DROP TABLE IF EXISTS `admin_permission_relation`;
CREATE TABLE `admin_permission_relation`  (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `admin_id` bigint(20) NULL DEFAULT NULL,
  `permission_id` bigint(20) NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用戶和權限關系表' ROW_FORMAT = Dynamic;

admin_role_relation表sql

DROP TABLE IF EXISTS `admin_role_relation`;
CREATE TABLE `admin_role_relation`  (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `admin_id` bigint(20) NULL DEFAULT NULL,
  `role_id` bigint(20) NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 17 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用戶和角色關系表' ROW_FORMAT = Dynamic;

role_permission_relation表sql

DROP TABLE IF EXISTS `role_permission_relation`;
CREATE TABLE `role_permission_relation`  (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `role_id` bigint(20) NULL DEFAULT NULL,
  `permission_id` bigint(20) NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 18 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用戶角色和權限關系表' ROW_FORMAT = Dynamic;
1 . pom導入依賴
<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <!-- redis -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!--SpringSecurity依賴配置-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- MyBatis 生成器 -->
        <dependency>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-core</artifactId>
            <version>1.3.7</version>
        </dependency>
        <!--MyBatis分頁插件-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.2.10</version>
        </dependency>
        <!--集成druid連接池-->
        <!--web監(jiān)控 http://127.0.0.1:8080/druid/index.html -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>
        <!--Mysql數(shù)據(jù)庫驅動-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!--Swagger-UI API文檔生產工具-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>
        <!--Hutool Java工具包-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.4.7</version>
        </dependency>
        <!--JWT(Json Web Token)登錄支持-->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>
        <!--參數(shù)校驗 javax.validation.constraints-->
        <!-- https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator -->
        <dependency>
            <groupId>org.hibernate.validator</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>6.1.5.Final</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
2. application配置
server:
  port: 8080

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/testmall?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
    username: root
    password: 123456
  redis:
    # redis服務器地址
    host: localhost
    # redis數(shù)據(jù)庫索引(默認為0)
    database: 0
    # redis服務器連接端口
    port: 6379
    # redis 服務器連接密碼 默認為空
    password:
    jedis:
      pool:
        # 連接池最大連接數(shù)(使用負值表示沒有限制)
        max-active: 8
        #  連接池最大阻塞等待時間(使用負值表示沒有限制)
        max-wait: -1ms
        # 連接池中的最大空閑連接
        max-idle: 8
        # 連接池中的最小空閑連接
        min-idle: 0
    # 連接超時時間(毫秒)
    timeout: 3000ms


# 自定義 redis key
redis:
  # 自定義 redis key
  key:
    prefix:
      authCode: "portal:authCode:"
    expire:
      #驗證碼超期時間
      authCode: 120

#自定義字段
jwt:
  secret: mySecret
  # jwt超期限時間 60*60*24
  expiration: 604800
  # JWT存儲的請求頭
  tokenHeader: Authorization
  # JWT負載中拿到開頭
  tokenHead: Bearer

#mybatis
mybatis:
  #mapper 映射文件地址
  mapper-locations:
    - classpath:mapper/*.xml
    - classpath:com/**/mapper/*.xml
  1. security 配置
/**
 * SpringSecurity的配置
 *
 * UserDetails:SpringSecurity定義用于封裝用戶信息的類(主要是用戶信息和權限),
 * 需要自行實現(xiàn);
 */
@Configuration
//開啟Security
@EnableWebSecurity
//保證post之前的注解可以使用
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UmsAdminService adminService;
    @Autowired
    private RestfulAccessDeniedHandler restfulAccessDeniedHandler;
    @Autowired
    private RestAuthenticationEntryPoint restAuthenticationEntryPoint;

    /**
     * 用于配置需要攔截的url路徑、jwt過濾器及出異常后的處理器;
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf()
                //由于使用的是JWT,我們這里不需要csrf
                .disable()//
                //基于token,所以不需要session
                .sessionManagement()
                //STATELESS不創(chuàng)建httpsession并不使用
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)//
                .and()
                .authorizeRequests()
                //允許對于網(wǎng)站靜態(tài)資源的無授權訪問
                .antMatchers(HttpMethod.GET,
                        "/",
                        "/*.html",
                        "/favicon.ico",
                        "/**/*.html",
                        "/**/*.css",
                        "/**/*.js",
                        "/swagger-resources/**",
                        "/v2/api-docs")
                .permitAll()
                //對登錄注冊要允許匿名訪問
                .antMatchers("/admin/login",
                        "/admin/register")
                .permitAll()
                //跨域請求會先進行一次options請求
                .antMatchers(HttpMethod.OPTIONS)
                .permitAll()
                //測試時全部運行訪問
//                .antMatchers("/**")
//                .permitAll()
                //除上面外的所有請求全部需要鑒權認證
                .anyRequest()
                .authenticated();
        //禁用緩存
        http.headers().cacheControl();
        //添加JWT filter 前置攔截
        http.addFilterBefore(jwtAuthenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class);
        //添加自定義未授權和未登錄結果返回
        http.exceptionHandling().accessDeniedHandler(restfulAccessDeniedHandler)
                .authenticationEntryPoint(restAuthenticationEntryPoint);
    }

    /**
     * 用于配置 UserDetailsService 及PasswordEncoder;
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService())
                .passwordEncoder(passwordEncoder());
    }

    /**
     * SpringSecurity定義的用于對密碼進行編碼及比對的接口,
     * 目前使用的是BCryptPasswordEncoder;
     * @return
     */
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    /**
     * SpringSecurity定義的核心接口,用于根據(jù)用戶名獲取用戶信息,需要自行實現(xiàn);
     * @return
     */
    @Bean
    public UserDetailsService userDetailsService(){
        //獲取登錄用戶信息,查詢用戶權限
//        return username -> {
//            UmsAdmin admin = adminService.getAdminByUsername(username);
//            if (admin !=null ){
//                List<UmsPermission> permissionList = adminService.getPermissionList(admin.getId());
//                return new AdminUserDetails(admin,permissionList);
//            }
//            throw new UsernameNotFoundException("用戶名或密碼錯誤");
//        };
        return new UserDetailsServiceImpl();
    }

    /**
     * 在用戶名和密碼校驗前添加的過濾器,
     * 如果有jwt的token,會自行根據(jù)token信息進行登錄。
     * @return
     */
    @Bean
    public JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter(){
        return new JwtAuthenticationTokenFilter();
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
}

攔截器
JwtAuthenticationTokenFilter

/**
 * JWT登錄授權過濾器
 * 在用戶名和密碼校驗前添加的過濾器,如果請求中有jwt的token且有效,
 * 會取出token中的用戶名,然后調用SpringSecurity的API進行登錄操作。
 * 請求 前置 過濾 token
 */
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {

    private static final Logger LOGGER =LoggerFactory.getLogger(JwtAuthenticationTokenFilter.class);
    @Autowired
    private UmsAdminService umsAdminService;

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Value("${jwt.tokenHeader}")
    private String tokenHeader;
    @Value("${jwt.tokenHead}")
    private String tokenHead;

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain filterChain) throws ServletException, IOException {
        String authHeader = request.getHeader(this.tokenHeader);
        LOGGER.info("checking authHeader:{}",authHeader);
        if (authHeader != null && authHeader.startsWith(this.tokenHead)){
            //The part after "Bearer "
            String authToken = authHeader.substring(this.tokenHead.length());
            LOGGER.info("checking authToken:{}",authToken);
            String username = jwtTokenUtil.getUserNameFromToken(authToken);
            LOGGER.info("checking username:{}",username);
            //SecurityContextHolder.getContext().getAuthentication() == null
            if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
               //
                UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);

                if (jwtTokenUtil.validateToken(authToken, userDetails)) {
                    UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
                    authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                    LOGGER.info("authenticated user:{}", username);
                    //打印用戶的權限
                    LOGGER.info("authenticated Authorities:{}", userDetails.getAuthorities().size());
                    //這個需要設置
                    //如果沒有這個會報 :Full authentication is required to access this resource
                    SecurityContextHolder.getContext().setAuthentication(authentication);
                }
            }
        }
        filterChain.doFilter(request,response);
    }

}

RestAuthenticationEntryPoint

/**
 * 當未登錄或者token失效訪問接口時,自定義的返回結果
 */
@Component
public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {
    private static final Logger LOGGER = LoggerFactory.getLogger(RestAuthenticationEntryPoint.class);

    @Override
    public void commence(HttpServletRequest request,
                         HttpServletResponse response,
                         AuthenticationException e) throws IOException, ServletException {
        LOGGER.info("RestAuthenticationEntryPoint commence 未登錄或者token失效訪問接口");
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json");
        response.getWriter().println(JSONUtil.parse(CommonResult.unauthorized(e.getMessage())));
        response.getWriter().flush();
    }

}

RestfulAccessDeniedHandler

/**
 * 當訪問接口沒有權限時,自定義的返回結果
 *
 */
@Component
public class RestfulAccessDeniedHandler implements AccessDeniedHandler {
    private static final Logger LOGGER = LoggerFactory.getLogger(RestfulAccessDeniedHandler.class);

    @Override
    public void handle(HttpServletRequest request,
                       HttpServletResponse response,
                       AccessDeniedException e) throws IOException, ServletException {
        LOGGER.info("RestfulAccessDeniedHandler handle 當訪問接口沒有權限時,自定義的返回結果");
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json");
        //沒有訪問權限
        response.getWriter().println(JSONUtil.parse(CommonResult.failed(e.getMessage())));
        response.getWriter().flush();
    }

}

service
UmsAdminService

/**
 *
 */
public interface UmsAdminService {

    //根據(jù)用戶名獲取后臺管理員
    UmsAdmin getAdminByUsername(String username);

    //注冊功能
    UmsAdmin register(UmsAdmin umsAdminParam);

    /**
     *  登錄功能
     * @param username
     * @param password
     * @return 生成的JWT的token
     */
    String login(String username,String password);

    //獲取用戶所有權限(包括角色權限和+-權限)
    List<UmsPermission> getPermissionList(Long adminId);

}

UmsAdminServiceImpl

/**
 *UmsAdminService實現(xiàn)類
 */
@Service
public class UmsAdminServiceImpl implements UmsAdminService {

    private static final Logger LOGGER = LoggerFactory.getLogger(UmsAdminServiceImpl.class);

    @Autowired
    private UserDetailsService userDetailsService;
    @Autowired
    private JwtTokenUtil jwtTokenUtil;
    @Autowired
    private PasswordEncoder passwordEncoder;

    @Value("${jwt.tokenHead}")
    private String tokenHead;

    @Autowired
    private UmsAdminMapper adminMapper;

    @Autowired
    private UmsAdminRoleRelationDao adminRoleRelationDao;

    //通過用戶名獲取管理員信息
    @Override
    public UmsAdmin getAdminByUsername(String username) {
        UmsAdminExample example = new UmsAdminExample();
        example.createCriteria().andUsernameEqualTo(username);
        List<UmsAdmin> adminList = adminMapper.selectByExample(example);
        if (adminList != null && adminList.size()>0){
            return adminList.get(0);
        }
        return null;
    }

    @Override
    public UmsAdmin register(UmsAdmin umsAdminParam) {
        UmsAdmin umsAdmin = new UmsAdmin();
        BeanUtils.copyProperties(umsAdminParam,umsAdmin);
        umsAdmin.setCreateTime(new Date());
        umsAdmin.setStatus(1);
        //查詢是否有相同用戶名的用戶
        UmsAdminExample example = new UmsAdminExample();
        example.createCriteria().andUsernameEqualTo(umsAdmin.getUsername());
        List<UmsAdmin> umsAdminList = adminMapper.selectByExample(example);
        if (umsAdminList.size()>0){
            return null;
        }
        //將密碼進行加密操作
        String encodePassword = passwordEncoder.encode(umsAdmin.getPassword());
        umsAdmin.setPassword(encodePassword);
        adminMapper.insert(umsAdmin);
        return umsAdmin;
    }

    @Override
    public String login(String username, String password) {
        String token = null;
        try {
            AdminUserDetails userDetails = null;
            List<UmsPermission> permissionList=null;
            //獲取用戶的信息
            UmsAdmin admin = getAdminByUsername(username);
            if (admin==null){
                throw new BadCredentialsException("用戶不存在");
            }
            permissionList = getPermissionList(admin.getId());
            userDetails = new AdminUserDetails(admin,permissionList);

            if (!passwordEncoder.matches(password,userDetails.getPassword())){
                throw new BadCredentialsException("密碼不正確");
            }
            UsernamePasswordAuthenticationToken authenticationToken =
                    new UsernamePasswordAuthenticationToken(userDetails,null,userDetails.getAuthorities());
//            //避免跨多個線程的競爭條件
            SecurityContextHolder.getContext().setAuthentication(authenticationToken);
            token = jwtTokenUtil.generateToken(admin);

//            UserDetails userDetails = userDetailsService.loadUserByUsername(username);
//            if (!passwordEncoder.matches(password, userDetails.getPassword())) {
//                throw new BadCredentialsException("密碼不正確");
//            }
//            UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
//            SecurityContextHolder.getContext().setAuthentication(authentication);
//            token = jwtTokenUtil.generateToken(userDetails);

        }catch (AuthenticationException e){
            LOGGER.warn("登錄異常:{}",e.getMessage());
        }
        return token;
    }

    @Override
    public List<UmsPermission> getPermissionList(Long id) {
        return adminRoleRelationDao.getPermissionList(id);
    }


}

UserDetailsServiceImpl

/**
 * UserDetailsService 實現(xiàn) 返回權限查詢
 */
public class UserDetailsServiceImpl implements UserDetailsService {
    private static final Logger logger = LoggerFactory.getLogger(UserDetailsServiceImpl.class);

    @Autowired
    private UmsAdminService umsAdminService;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        UmsAdmin admin = umsAdminService.getAdminByUsername(username);
        if (admin !=null ){
            List<UmsPermission> permissionList = umsAdminService.getPermissionList(admin.getId());
            return new AdminUserDetails(admin,permissionList);
        }
        throw new UsernameNotFoundException("用戶名或密碼錯誤");

    }
}

/**
 * 用戶與角色管理自定義Dao
 * mapper映射
 */
public interface UmsAdminRoleRelationDao {

    //獲取用戶所有權限(包括+-權限)
    public List<UmsPermission> getPermissionList(@Param("adminId") Long adminId);

}

UmsAdminRoleRelationDao.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mall.tiny04.dao.UmsAdminRoleRelationDao">

<select id="getPermissionList" resultMap="com.mall.tiny04.mbg.mapper.UmsPermissionMapper.BaseResultMap">
     SELECT
            p.*
        FROM
            admin_role_relation ar
            LEFT JOIN role r ON ar.role_id = r.id
            LEFT JOIN role_permission_relation rp ON r.id = rp.role_id
            LEFT JOIN permission p ON rp.permission_id = p.id
        WHERE
            ar.admin_id = #{adminId}
            AND p.id IS NOT NULL
            AND p.id NOT IN (
                SELECT
                    p.id
                FROM
                    admin_permission_relation pr
                    LEFT JOIN permission p ON pr.permission_id = p.id
                WHERE
                    pr.type = - 1
                    AND pr.admin_id = #{adminId}
            )
        UNION
        SELECT
            p.*
        FROM
            admin_permission_relation pr
            LEFT JOIN permission p ON pr.permission_id = p.id
        WHERE
            pr.type = 1
            AND pr.admin_id = #{adminId}

</select>
</mapper>


controller方法上添加權限



image.png

    @PostMapping("/update/{id}")
    // id 是否有 update權限
    @PreAuthorize("hasPermission(#id,'update')")
    //是否有創(chuàng)建權限
    //@PreAuthorize("hasAuthority('create')") 
    // 是否有admin權限
   // @PreAuthorize("hasRole('admin')")
    @ResponseBody
    public CommonResult updateBrand(@PathVariable("id") Long id,
                                    @RequestBody PmsBrand pmsBrand,
                                    BindingResult result){
    }
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容