ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Rbac-manager权限管理项目

2021-10-14 22:29:58  阅读:155  来源: 互联网

标签:return token private class Rbac manager Result 权限 public


一、RBAC-MANAGER(用户权限管理)

1.pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.5</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.xgj</groupId>
    <artifactId>rbac-test-01</artifactId>
​
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt -->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>
​
​
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.6</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.3.4</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.78</version>
        </dependency>
​
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
            <version>5.1.6</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
​
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>
​
</project>
​

2.application.yml

server:
  port: 8082
  servlet:
    context-path: /rbac
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/incodedb
    username: root
    password: root
    driver-class-name: com.mysql.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
  jackson:
    date-format: yyyy-MM-dd
mybatis-plus:
  global-config:
    db-config:
      id-type: auto
      table-prefix: t_
logging:
  level:
    com.xgj.mapper: debug

Security

1.LoginUserDetailService

@Component
public class LoginUserDetailService implements UserDetailsService {
​
    @Autowired
    private UserService userService;
​
    @Autowired
    private AuthService authService;
​
    //用户登录的时候调用,根据用户输入的用户名去查询密码
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
​
        System.out.println("--------------------LoginUserDetailService-------------------------");
        System.out.println("用户【"+username+"】正在做登录操作。。。。");
        //1.根据用户名查询密码
       User user= userService.getUserByUsername(username);
​
       //2.判断用户是否存在
        if (user == null) {
                throw new RbacException(1001,"用户不存在");
        }
​
        //>查询当前用户的角色
        List<String> roleNameList=authService.getRoleListByUid(user.getId());
​
​
        //.3创建一个的登录的User对象
        SecurityUser securityUser=new SecurityUser();
        securityUser.setCurrentUser(user);
        securityUser.setRoleNameList(roleNameList);
​
​
    //4.返回SecurityUser,当时候SpringSecurity调用这个类中getPassword()来完成密码的比对
        return securityUser;
    }
}

2.JwtTokenFilter

​
@Component
public class JwtTokenFilter extends OncePerRequestFilter {
​
    @Autowired
    private LoginUserDetailService userDetailService;
​
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
​
        //1.获取Token
        String token = request.getHeader(SecurityConstant.TOKEN_NAME);
​
        //2.检验token
        Claims claim = JwtUtil.getClaim(token);
        if (claim == null) {
            Result error=Result.error();
            error.put("code",501);//501代表Token有误
            error.put("msg","没有携带token或token过期");
​
            ResponseUtil.out(response, error);
            return;
        }
        //3.token检验成功后从token中获取主体信息
        String username = claim.get(SecurityConstant.USER_NAME, String.class);
         List roleName= claim.get("roleName", List.class);
​
​
        //4.根据用户名查询用户信息
        SecurityUser securityUser = (SecurityUser) userDetailService.loadUserByUsername(username);
        List<String> roleNameList = securityUser.getRoleNameList();
​
        //5.封装
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(securityUser,null,securityUser.getAuthorities());
​
        //6.全局登录设置
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
​
        //7.放行
        filterChain.doFilter(request,response);
​
​
    }
}

3.UrlAuthenFilter

​
@Component
public class UrlAuthenFilter {
​
    @Autowired
    private PermissionService permissionService;
​
    @Autowired
    private AntPathMatcher antPathMatcher;
​
    @Autowired
    private AuthService authService;
​
    /**
    *@Author xiaogongjue
    *@Date2021/10/11 21:46
    *@Description request当前的请求  authentication主体
    */
    public boolean checkUrlAuthen(HttpServletRequest request, Authentication authentication){
​
        //1.定义一个标识,如果有权限为true
        boolean flag=false;
​
        //2.获取当前的请求
        String reqUrl = request.getRequestURL().toString();
​
        //3.获取Db中的全部URL
        List<Permission> dbUrlList = permissionService.allUrlList();
​
        //4.遍历dbUrllIst与当前的请求的Url----》urlId---->角色
​
        for (Permission permission : dbUrlList) {
​
            if(antPathMatcher.match(permission.getUrl(),reqUrl)){
                    //6.根据菜单id查询角色(访问这些url需要这些的角色)
              List<String> roleCodes= authService.getRoleCodeByPid(permission.getId());
​
              //7.判断当前主体是否有这写角色的一个
            SecurityUser securityUser= (SecurityUser) authentication.getPrincipal();
                List<String> userRoleNameList = securityUser.getRoleNameList();
                for (String roleCode : userRoleNameList) {
                        //如果是包含关系就是有权限
                    if(roleCodes.contains(roleCode)){
​
                        flag=true;
                    }
​
                }
​
            }
​
        }
        return flag;
    }
​

4.UserAccessDeniedHandler用户没有权限处理器

​
@Component
public class UserAccessDeniedHandler implements AccessDeniedHandler {
​
​
    @Override
    public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException {
​
        Result error=Result.error();
        error.put("code",502);//502代表没有权限
        error.put("msg","你没有权限访问。。");
​
        ResponseUtil.out(httpServletResponse, error);
    }
}

5.UserAuthenticationEntryPoint用户没有登录(授权)

@Component
public class UserAuthenticationEntryPoint implements AuthenticationEntryPoint {
    @Override
    public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
        ResponseUtil.out(httpServletResponse, Result.error("你还没有登录,请先登录"));
    }
}

6.UserLoginFilter用户登录的过滤器

​
@Component
public class UserLoginFilter extends UsernamePasswordAuthenticationFilter {
​
​
    @Autowired//从IOC容器注入authenticationManager给父类初始化
    @Override
    public void setAuthenticationManager(AuthenticationManager authenticationManager) {
        super.setAuthenticationManager(authenticationManager);
    }
​
    //认证成功时调用
    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
        //1.当前登录的主体
        SecurityUser  securityUser = (SecurityUser) authResult.getPrincipal();
        System.out.println("欢迎:【"+securityUser+"】登录成功");
        //2.定义需要放入Token中的数据
        Map<String,Object> map=new HashMap<>();
        map.put(SecurityConstant.USER_NAME,securityUser.getUsername());
​
        map.put("roleName",securityUser.getRoleNameList());
​
        //3.创建Token
        String token = JwtUtil.createToken(map);
​
        //4.响应登录成功
​
        ResponseUtil.out(response,Result.putDate(SecurityConstant.TOKEN_NAME,token));
​
    }
    //认证失败后调用
    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
        ResponseUtil.out(response, Result.error("用户名或密码错误,请你重试~~"));
​
    }
}
​

mybatis-plus

1.UserMetaHandler(数据库自动填充)

/**
 * @Author xiaogongjue
 * @Date2021/10/6 12:56
 * @Description 自动填字段
 */
@Component
public class UserMetaHandler implements MetaObjectHandler {
    @Override
    public void insertFill(MetaObject metaObject) {
        System.out.println("字段自动填充");
        Object status = getFieldValByName("status", metaObject);
        if (status == null) {
            setFieldValByName("status", 1, metaObject);
        }
        Object createTime = getFieldValByName("createTime", metaObject);
        if (createTime == null) {
            setFieldValByName("createTime", new Date(), metaObject);
        }
​
    }
​
    @Override
    public void updateFill(MetaObject metaObject) {
​
    }
}

2.common包下新建拣utils

工具类Result

public class Result extends HashMap<String, Object> {
​
    public Result() {
        //0代表成功,非0代表失败
        super.put("code", 0);
        super.put("msg", "success");
​
    }
​
    public static Result ok() {
        //响应成功
        return new Result();
    }
​
    //响应成功带有成功的提示信息
    public static Result ok(String msg) {
        Result r = new Result();
        r.put("msg", msg);
        return r;
    }
​
    //响应失败
    public static Result error() {
        Result r = new Result();
        r.put("code", 500);
        r.put("msg", "error");
        return r;
    }
​
    //响应失败带有失败的原因信息
    public static Result error(String msg) {
        Result r = Result.error();
        r.put("msg", msg);
        return r;
    }
​
    //对成功与否的判断
    public static Result out(Object value) {
​
        if (value instanceof Boolean) {//对操作结果是Boolean类型的操作,比例更新,删除
            if ((boolean) value) {
                return Result.ok();
            } else {
                return Result.error();
            }
​
        }else if(value instanceof Integer){//对操作结果是Integer类型的操作,比例插入
            if((Integer)value>0){
                return Result.ok();
​
            }else{
                return Result.error();
            }
​
        }
            return Result.error();
    }
    //将数据以键值对的形式存起来
    public static Result putDate(String key,Object object){
        Result r=new Result();
        r.put(key,object);
        return r;
    }
​
}
public class ResponseUtil {
​
    public static void out(HttpServletResponse response,Result r){
​
        //设置响应的数类型为JSON,编码格式为UTF-8
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        response.setCharacterEncoding("utf-8");
​
        try {
            //将Result对象转成JSON字符串写出去
            response.getWriter().write(JSON.toJSONString(r));
        } catch (IOException e) {
            e.printStackTrace();
        }
​
    }
}
public class JwtUtil {
​
    private static final String sign = "2105-rbac"; // 签名
    private static final long EXPIRE = 1000 * 60 * 30; // 过期时间 30m
​
    /**
     * 生成token
     *
     * @return
     */
    public static String createToken(Map<String, Object> map) {
        Date nowDate = new Date();
        //过期时间
        Date expireDate = new Date(nowDate.getTime() + EXPIRE);
        return Jwts.builder()
                .setClaims(map) // 载荷
                .setIssuedAt(nowDate) // 当前时间
                .setExpiration(expireDate) // 过期时间
                .signWith(SignatureAlgorithm.HS512, sign) // 签名
                .compact();
    }
​
    /**
     * 解析Claims
     *
     * @param token
     * @return
     */
    public static Claims getClaim(String token) {
        Claims claims = null;
        try {
            claims = Jwts.parser()
                    .setSigningKey(sign)
                    .parseClaimsJws(token)
                    .getBody();
        } catch (Exception e) {
            System.out.println("token解析失败");
        }
        return claims;
    }
​
    /**
     * 验证token是否失效
     *
     * @param token
     * @return true:过期   false:没过期
     */
    public static boolean isExpired(String token) {
        try {
            final Date expiration = getExpiration(token);
            return expiration.before(new Date());
        } catch (ExpiredJwtException expiredJwtException) {
            return true;
        }
    }
​
    /**
     * 获取jwt失效时间
     */
    public static Date getExpiration(String token) {
        return getClaim(token).getExpiration();
    }
}

config包下

/**
 * @Author xiaogongjue
 * @Date2021/10/11 11:31
 * @Description  跨越与拦截器
 */
@Component
public class CORSFilter implements Filter {
​
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
​
        HttpServletResponse response = (HttpServletResponse) servletResponse;
​
        response.setHeader("Access-Control-Allow-Origin", "*");
​
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, HEAD");
​
        response.setHeader("Access-Control-Max-Age", "3600");
​
        response.setHeader("Access-Control-Allow-Headers", "*");
​
        filterChain.doFilter(servletRequest,response);
​
    }
}
​
/**
 * @Author xiaogongjue
 * @Date2021/10/6 11:26
 * @Description 配置拦截器
 */
@Configuration
public class MPconfig {
​
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
     interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));//将分页拦截器加入到MP配置中
​
            return interceptor;
    }
​
}
​
@Configuration
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
​
    @Autowired
    private LoginUserDetailService loginUserDetailService;
​
    //给IOC容器中放入一个密码加密的算法
    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    //认证过滤器
    @Autowired
    private UserLoginFilter userLoginFilter;
    //没有权限处理器
    @Autowired
    private UserAccessDeniedHandler userAccessDeniedHandler;
    //没有登录(认证)处理器
    @Autowired
    private UserAuthenticationEntryPoint userAuthenticationEntryPoint;
​
    @Autowired
    private JwtTokenFilter jwtTokenFilter;
​
​
    // 复写父类中的 AuthenticationManager 添加IOC容器中
    @Bean
    @Override
    protected AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }
​
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
                .userDetailsService(loginUserDetailService) // 设置userDetails
                .passwordEncoder(passwordEncoder()); // 设置加密算法
    }
​
    @Override
    protected void configure(HttpSecurity http) throws Exception {
       http.addFilter(userLoginFilter)
               //jwtTokenFilter要在BasicAuthenticationFilter之前运行
               .addFilterBefore(jwtTokenFilter, BasicAuthenticationFilter.class)
               .exceptionHandling().accessDeniedHandler(userAccessDeniedHandler)//没有权限处理器
               .authenticationEntryPoint(userAuthenticationEntryPoint)//没有认证的处理器
                //.and().authorizeRequests().anyRequest().authenticated()//所有资源度需要认证后才能访问
                //声明用Token登录
          .and().authorizeRequests().anyRequest().access("@urlAuthenFilter.checkUrlAuthen(request,authentication)")
​
               .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
       .and().csrf().disable()
               ;
    }
}
​
​
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
​
//    @Override
//    public void addCorsMappings(CorsRegistry registry) {
//        registry.
//                addMapping("/**")
//                .allowedMethods("POST","GET","DELETE","PUT")
//                .allowedHeaders("*")
//                .allowedOrigins("*");
//
//
//    }
​
    @Autowired
    private CORSFilter corsFilter;
​
    @Bean
    public AntPathMatcher antPathMatcher(){
        return new AntPathMatcher();
    }
​
    @Bean
    public FilterRegistrationBean testFilterRegistration() {
​
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(corsFilter);
        registration.addUrlPatterns("/*");
        registration.setName("corsFilter");
        registration.setOrder(Integer.MIN_VALUE);
        return registration;
    }
}

entity(权限实体)

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Permission implements Serializable {
   @TableId
    private Integer id;
    private String name;
    private String url;
    private Integer type;
    private Integer status;
    private Integer pid;//父ID
    @TableField(exist = false)
    private String pname;//告诉MP表中不存在这个字段
}
​

权限controller

@RestController
@RequestMapping("/per/")
public class PermissionController {
​
    @Autowired
    private PermissionService permissionService;
​
    @PostMapping("save")
    public Result savePer(@RequestBody Permission permission){
        boolean save = permissionService.save(permission);
        return Result.out(save);
​
    }
​
    @GetMapping("/treeList")
    public Result treeList(){//后端返回的是简单的JSON数据
     return Result.putDate("data", permissionService.treeList());
​
    }
​
    @PostMapping("page")
    public Result pagePer(@RequestBody Page<Permission> permissionPage){
        Page<Permission> page = permissionService.page(permissionPage);
        return Result.putDate("page",page);
    }
    @GetMapping("delete/{id}")
    public Result deletePer(@PathVariable Integer id){
      return Result.out(permissionService.removeById(id));
​
    }
    @PostMapping("update")
    public Result updatePer(@RequestBody Permission permission){
       return Result.out(permissionService.updateById(permission));
    }
    @GetMapping("getById/{id}")
    public Result getPerById(@PathVariable Integer id){
        Permission permission = permissionService.getAllById(id);
        return Result.putDate("permission",permission);
    }
}

PermissionMapper

public interface PermissionMapper extends BaseMapper<Permission> {
    List<Permission> treeList();
​
    Permission getAllById(Integer id);
​
    List<Permission> allUrlList();
​
}

PermissionService

public interface PermissionService extends IService<Permission> {
    List<Permission> treeList();
​
    Permission getAllById(Integer id);
​
    List<Permission> allUrlList();
​
​
}

在resource下新建一个mapper目录,存放PermissionMapper.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.xgj.mapper.PermissionMapper">
​
   <select id="getAllById" resultType="com.xgj.entity.Permission">
SELECT t1.*,t2.`name` AS pname FROM t_permission t1 LEFT JOIN t_permission t2 ON t1.`pid`=t2.`id` WHERE t1.id=#{id}
</select>
​
    <select id="treeList" resultType="com.xgj.entity.Permission">
SELECT t1.*,t2.`name` as pname from t_permission t1 LEFT JOIN t_permission t2 ON (t1.pid=t2.id)
</select>
​
<select id="allUrlList" resultType="com.xgj.entity.Permission">
​
SELECT * FROM t_permission p WHERE LENGTH(p.url)>0
​
</select>
​
</mapper>

标签:return,token,private,class,Rbac,manager,Result,权限,public
来源: https://blog.csdn.net/weixin_43562801/article/details/120774126

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有