IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Spring boot 整合Spring Security Jwt -> 正文阅读

[Java知识库]Spring boot 整合Spring Security Jwt

记录学习Spring boot 整合Spring Security Jwt

学习参考 – 慢慢的干货

https://shimo.im/docs/OnZDwoxFFL8bnP1c/read

首先创建Spring Boot项目以及导入依赖

    <dependencies>
        <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>

        <!--mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.22</version>
        </dependency>

        <!--mybatis-plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.3.1.tmp</version>
        </dependency>

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.3.1.tmp</version>
        </dependency>

        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity</artifactId>
            <version>1.7</version>
        </dependency>

        <!--lombok-->
        <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>

        <!--security-->
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!--jwt-->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>

        <!--hutool工具-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.5.7</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>

    </dependencies>

application.yml配置

# 数据库相关配置
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/securitytext?serverTimezone=GMT&characterEncoding=utf-8
    username: root
    password: 1233
    dbcp2:
      test-on-borrow: true
      validation-query: SELECT 1
    hikari:
      max-lifetime: 30000
  servlet:
    multipart:
      max-file-size: 1024MB
      max-request-size: 1024MB

# mybatis-plus相关配置
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
#  mapper-locations: classpath*:/mapper/**Mapper.xml

# 服务端口号
server:
  port: 8030

# jwt配置
xiaojiang:
  jwt:
    secret: f4e2e52034348f86b67cde581c0f9eb5
    expire: 604800
    header: Authorization

创建数据库

-- ----------------------------
-- Table structure for sys_user
-- ----------------------------

DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '用户id',
  `username` varchar(64) DEFAULT NULL COMMENT '用户名',
  `password` varchar(64) DEFAULT NULL COMMENT '用户密码',
  `avatar` varchar(255) DEFAULT NULL COMMENT '用户头像',
  `email` varchar(64) DEFAULT NULL COMMENT '用户邮箱',
  `city` varchar(64) DEFAULT NULL COMMENT '城市',
  `created_time` datetime DEFAULT NULL COMMENT '用户创建时间',
  `updated_time` datetime DEFAULT NULL COMMENT '用户修改时间',
  `last_login_time` datetime DEFAULT NULL COMMENT '用户上次登录时间',
  `statu` int(5) NOT NULL COMMENT '用户状态 1可用|0不可用',
  PRIMARY KEY (`id`),
  UNIQUE KEY `UK_USERNAME` (`username`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of sys_user
-- ----------------------------
INSERT INTO `sys_user` VALUES ('1', 'admin', '$2a$10$R7zegeWzOXPw871CmNuJ6upC0v8D373GuLuTw8jn6NET4BkPRZfgK', 'https://image-1300566513.cos.ap-guangzhou.myqcloud.com/upload/images/5a9f48118166308daba8b6da7e466aab.jpg', '123@qq.com', '广州', '2021-01-12 22:13:53', '2021-01-16 16:57:32', '2020-12-30 08:38:37', '1');

INSERT INTO `sys_user` VALUES ('2', 'test', '$2a$10$0ilP4ZD1kLugYwLCs4pmb.ZT9cFqzOZTNaMiHxrBnVIQUGUwEvBIO', 'https://image-1300566513.cos.ap-guangzhou.myqcloud.com/upload/images/5a9f48118166308daba8b6da7e466aab.jpg', 'test@qq.com', null, '2021-01-30 08:20:22', '2021-01-30 08:55:57', null, '1');


-- ----------------------------
-- Table structure for sys_role
-- ----------------------------

DROP TABLE IF EXISTS `sys_role`;
CREATE TABLE `sys_role` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '角色id',
  `name` varchar(64) NOT NULL COMMENT '角色名称',
  `code` varchar(64) NOT NULL COMMENT '角色',
  `created_time` datetime DEFAULT NULL COMMENT'角色创建时间',
  `updated_time` datetime DEFAULT NULL COMMENT '角色修改时间',
  `statu` int(5) NOT NULL COMMENT '角色状态 1可用|0不可用',
  PRIMARY KEY (`id`),
  UNIQUE KEY `name` (`name`) USING BTREE,
  UNIQUE KEY `code` (`code`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of sys_role
-- ----------------------------
INSERT INTO `sys_role` VALUES ('1', '超级管理员', 'admin', '2021-01-16 13:29:03', '2021-01-17 15:50:45', '1');

INSERT INTO `sys_role` VALUES ('2', '普通用户', 'normal', '2021-01-04 10:09:14', '2021-01-30 08:19:52', '1');


-- ----------------------------
-- Table structure for sys_user_role
-- ----------------------------
DROP TABLE IF EXISTS `sys_user_role`;
CREATE TABLE `sys_user_role` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `user_id` bigint(20) NOT NULL COMMENT '用户id',
  `role_id` bigint(20) NOT NULL COMMENT '角色id',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8mb4;


-- ----------------------------
-- Records of sys_user_role
-- ----------------------------
INSERT INTO `sys_user_role` VALUES ('1', '1', '1');
INSERT INTO `sys_user_role` VALUES ('2', '1', '2');
INSERT INTO `sys_user_role` VALUES ('3', '2', '2');

在这里插入图片描述

使用mybatis-plus代码生成器

public class CodeGenerator {

    public static String scanner(String tip) {
        Scanner scanner = new Scanner(System.in);
        StringBuilder help = new StringBuilder();
        help.append("请输入" + tip + ":");
        System.out.println(help.toString());
        if (scanner.hasNext()) {
            String ipt = scanner.next();
            if (StringUtils.isNotEmpty(ipt)) {
                return ipt;
            }
        }
        throw new MybatisPlusException("请输入正确的" + tip + "!");
    }


    public static void main(String[] args) {
        // 代码生成器
        AutoGenerator mpg = new AutoGenerator();

        // 全局配置
        GlobalConfig gc = new GlobalConfig();
        String projectPath = System.getProperty("user.dir");
        gc.setOutputDir(projectPath + "/src/main/java");
        gc.setAuthor("Mr.jiang");
        gc.setOpen(false);
        gc.setServiceName("%sService");
        mpg.setGlobalConfig(gc);

        // 数据源配置
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setDbType(DbType.MYSQL);
        dsc.setUrl("jdbc:mysql://localhost:3306/securitytext?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai");
        dsc.setDriverName("com.mysql.cj.jdbc.Driver");
        dsc.setUsername("root");
        dsc.setPassword("1233");
        mpg.setDataSource(dsc);

        // 包配置
        PackageConfig pc = new PackageConfig();
        pc.setModuleName(null);
        pc.setParent("com.jsp");
        mpg.setPackageInfo(pc);


        // 策略配置
        StrategyConfig strategy = new StrategyConfig();
        strategy.setNaming(NamingStrategy.underline_to_camel);
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
        strategy.setEntityLombokModel(true);
        strategy.setRestControllerStyle(true);
        strategy.setInclude(scanner("表名,多个英文逗号分割").split(","));
        strategy.setControllerMappingHyphenStyle(true);
        strategy.setTablePrefix("sys_");
        mpg.setStrategy(strategy);
        mpg.execute();

    }
}

创建mybatis-plus配置类

@Configuration
public class MybatisPlusConfig {

    // 分页配置
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
        return paginationInterceptor;
    }
}
@Component
public class MyMetaObjectConfig implements MetaObjectHandler {

	// 自动插入、更新
    @Override
    public void insertFill(MetaObject metaObject) {
        this.setFieldValByName("createTime", new Date(), metaObject);
        this.setFieldValByName("updateTime", new Date(), metaObject);
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        this.setFieldValByName("updateTime", new Date(), metaObject);
    }
}

这里是为了entiy类中的字段

      /**
     * 用户创建时间
     */
      @TableField(fill = FieldFill.INSERT)
      @JsonFormat(pattern = "yyyy-MM-dd HH:mm", timezone = "GMT+8")
      private LocalDateTime createdTime;

      /**
     * 用户修改时间
     */
      @TableField(fill = FieldFill.INSERT)
      @JsonFormat(pattern = "yyyy-MM-dd HH:mm", timezone = "GMT+8")
      private LocalDateTime updatedTime;

      /**
     * 用户上次登录时间
     */
      @TableField(fill = FieldFill.INSERT_UPDATE)
      @JsonFormat(pattern = "yyyy-MM-dd HH:mm", timezone = "GMT+8")
      private LocalDateTime lastLoginTime;

Result结果集

@Data
public class Result implements Serializable {

    private int code;
    private String message;
    private Object data;

    Result(int code,String message,Object data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }

    Result(int code,String message) {
        this.code = code;
        this.message = message;
    }
}
public enum ResultCode {

    //成功
    SUCCESS(200),

    //失败
    FAIL(400),

    //用户未认证
    UNAUTHORIZED(401),

    //url找不到
    NOT_FOUND(404),

    //访问受限
    FORBIDDEN(403),

    //服务器错误
    INTERNAL_SERVER_ERROR(500);

    public int code;

    ResultCode(int code) {
        this.code = code;
    }
}
public class ResultFactory {

    //成功
    public static Result successful(Object data) {
        return buildResult(ResultCode.SUCCESS, "成功", data);
    }

    //失败
    public static Result fail(String message) {
        return buildResult(ResultCode.FAIL, message, null);
    }

    public static Result buildResult(int ResultCode, String message, Object data) {
        return new Result(ResultCode, message, data);
    }


    public static Result buildResult(ResultCode ResultCode, String message, Object data) {
        return new Result(ResultCode.code, message, data);
    }

    public static Result buildResult(ResultCode ResultCode, String message) {
        return new Result(ResultCode.code, message);
    }

}

** 重点 Spring Security 配置类

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private LoginFailureHandler loginFailureHandler;

    @Autowired
    private LoginSuccessHandler loginSuccessHandler;

    @Autowired
    private UserDetailsServiceImpl userDetailsService;

    @Autowired
    private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;

    @Autowired
    private JwtAccessDeniedHandler jwtAccessDeniedHandler;

    @Autowired
    private JwtLogoutSuccessHandler jwtLogoutSuccessHandler;

    @Bean
    JWTAuthenticationFilter jwtAuthenticationFilter() throws Exception {

        return new JWTAuthenticationFilter(authenticationManager());
    }

    @Bean
    BCryptPasswordEncoder bCryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }

    //白名单
    public static final String[] URL_WHITELIST = {
            "/favicon.ico",
            "/login",
            "/logout",
    };

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().and().csrf().disable()
                //关闭session
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)

                .and()
                .formLogin()
                .successHandler(loginSuccessHandler)
                .failureHandler(loginFailureHandler)


                //退出
                .and()
                .logout()
                .logoutSuccessHandler(jwtLogoutSuccessHandler)

                //资源访问控制
                .and()
                .authorizeRequests()

                //白名单
                .antMatchers(URL_WHITELIST).permitAll()

                //其他请求需要认证
                .anyRequest().authenticated()

                //异常处理器
                .and()
                .exceptionHandling()
                .authenticationEntryPoint(jwtAuthenticationEntryPoint)
                .accessDeniedHandler(jwtAccessDeniedHandler)

                .and()
                .addFilter(jwtAuthenticationFilter());


    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService);
    }
}

重写UserDetails

public class MyUserDetails implements UserDetails {

    private Integer id;

    private String password;

    private final String username;

    private final Collection<? extends GrantedAuthority> authorities;

    private final boolean accountNonExpired;

    private final boolean accountNonLocked;

    private final boolean credentialsNonExpired;

    private final boolean enabled;

    public MyUserDetails(Integer id, String username, String password, Collection<? extends GrantedAuthority> authorities) {
        this(id, username, password, true, true, true, true, authorities);
    }


    public MyUserDetails(Integer id, String username, String password, boolean enabled, boolean accountNonExpired,
                         boolean credentialsNonExpired, boolean accountNonLocked,
                         Collection<? extends GrantedAuthority> authorities) {
        Assert.isTrue(username != null && !"".equals(username) && password != null,
                "Cannot pass null or empty values to constructor");
        this.id = id;
        this.username = username;
        this.password = password;
        this.enabled = enabled;
        this.accountNonExpired = accountNonExpired;
        this.credentialsNonExpired = credentialsNonExpired;
        this.accountNonLocked = accountNonLocked;
        this.authorities = authorities;
    }


    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return this.authorities;
    }

    @Override
    public String getPassword() {
        return this.password;
    }

    @Override
    public String getUsername() {
        return this.username;
    }

    @Override
    public boolean isAccountNonExpired() {
        return this.accountNonExpired;
    }

    @Override
    public boolean isAccountNonLocked() {
        return this.accountNonLocked;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return this.credentialsNonExpired;
    }

    @Override
    public boolean isEnabled() {
        return this.enabled;
    }
}

重写UserDetailsService

@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserService userService;

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

        //查询数据库判断username是否存在,如果不存在则抛出异常UsernameNotFoundException
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("username", username);
        User user = userMapper.selectOne(wrapper);
        if (user == null) {
            throw new UsernameNotFoundException("用户名或密码不正确!");
        }
        //从数据库查出的用户信息id,username,password,authorityList

        List<GrantedAuthority> authorityList = getUserAuthority(user.getId());
        return new MyUserDetails(user.getId(), user.getUsername(), user.getPassword(), authorityList);
    }

    public List<GrantedAuthority> getUserAuthority(Integer id) {
        return AuthorityUtils.commaSeparatedStringToAuthorityList(
                userService.getUserAuthorityInfo(id)
        );
    }
}
public interface UserRoleMapper extends BaseMapper<UserRole> {

    @Select("SELECT user_id,role_id,code,name FROM sys_user_role JOIN sys_role ON sys_user_role.role_id = sys_role.id WHERE user_id = #{uid};")
    List<RolesVo> selectRoles(Integer uid);

}

VO类

RolesVo

@Data
@AllArgsConstructor
@NoArgsConstructor
public class RolesVo {

	//角色
    String code;
	//角色名称
    String name;

}
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private UserRoleMapper userRoleMapper;

    @Autowired
    private UserMapper userMapper;

    //根据用户id获取用户角色
    @Override
    public String getUserAuthorityInfo(Integer id) {
        List<RolesVo> roles = userRoleMapper.selectRoles(id);

        String roleNames = roles.stream().map(role -> "ROLE_" + role.getCode()).collect(Collectors.joining(","));

//        ROLE_admin,ROLE_normal,sys:user:list...,
        String authority = roleNames.concat(",").concat("sys:user:list");
        System.out.println("authority->" + authority);

        return authority;
    }

    @Override
    public User getByUsername(String username) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("username", username);
        User user = userMapper.selectOne(wrapper);
        return user;
    }
}

这里还有菜单管理的 String authority = roleNames.concat(",").concat("sys:user:list");以后还会补上的

在这里插入图片描述

LoginSuccessHandler

@Component
public class LoginSuccessHandler implements AuthenticationSuccessHandler {

    @Autowired
    private JwtUtil jwtUtil;


    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        response.setContentType("application/json;charset=UTF-8");
        ServletOutputStream outputStream = response.getOutputStream();

        // 生成jwt返回
        String token = jwtUtil.generateToken(authentication.getName());
        response.setHeader(jwtUtil.getHeader(), token);

        Result result = ResultFactory.successful("");
        outputStream.write(JSONUtil.toJsonStr(result).getBytes("UTF-8"));
        outputStream.flush();
        outputStream.close();
    }
}

LoginFailureHandler

@Component
public class LoginFailureHandler implements AuthenticationFailureHandler {

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
        response.setContentType("application/json;charset=UTF-8");
        ServletOutputStream outputStream = response.getOutputStream();
        Result result = ResultFactory.fail("Bad credentials".equals(exception.getMessage()) ? "用户名或密码不正确" : exception.getMessage());
        outputStream.write(JSONUtil.toJsonStr(result).getBytes("UTF-8"));

        outputStream.flush();
        outputStream.close();
    }
}

JwtLogoutSuccessHandler

@Component
public class JwtLogoutSuccessHandler implements LogoutSuccessHandler {

    @Autowired
    private JwtUtil jwtUtil;

    @Override
    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        if (authentication != null) {
            new SecurityContextLogoutHandler().logout(request, response, authentication);
        }
        response.setContentType("application/json;charset=UTF-8");
        ServletOutputStream outputStream = response.getOutputStream();
        response.setHeader(jwtUtil.getHeader(), "");

        Result result = ResultFactory.successful("");

        outputStream.write(JSONUtil.toJsonStr(result).getBytes("UTF-8"));

        outputStream.flush();
        outputStream.close();
    }
}

JwtAuthenticationEntryPoint

@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {

    @Override
    public void commence(HttpServletRequest httpServletRequest, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException {
        response.setContentType("application/json;charset=UTF-8");
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        ServletOutputStream outputStream = response.getOutputStream();

        Result result = ResultFactory.buildResult(ResultCode.UNAUTHORIZED, "请先登录!");

        outputStream.write(JSONUtil.toJsonStr(result).getBytes("UTF-8"));
        outputStream.flush();
        outputStream.close();
    }
}

JwtAccessDeniedHandler

@Component
public class JwtAccessDeniedHandler implements AccessDeniedHandler {

    @Override
    public void handle(HttpServletRequest httpServletRequest, HttpServletResponse response, AccessDeniedException e) throws IOException, ServletException {

        response.setContentType("application/json;charset=UTF-8");
        response.setStatus(HttpServletResponse.SC_FORBIDDEN);
        ServletOutputStream outputStream = response.getOutputStream();

        //Result result = ResultFactory.fail(e.getMessage());
        Result result = ResultFactory.buildResult(ResultCode.FORBIDDEN,"权限不足");


        outputStream.write(JSONUtil.toJsonStr(result).getBytes("UTF-8"));
        outputStream.flush();
        outputStream.close();
    }
}

jwt相关配置

JwtUtil

@Data
@Component
@ConfigurationProperties(prefix = "xiaojiang.jwt")
public class JwtUtil {

    private long expire;
    private String secret;
    private String header;

    //生成JWT
    public String generateToken(String username) {

        Date exireDate = new Date(new Date().getTime() + 1000 * expire);

        return Jwts.builder()
                .setHeaderParam("typ", "JWT")
                .setSubject(username)
                .setIssuedAt(new Date())
                .setExpiration(exireDate)
                .signWith(SignatureAlgorithm.HS256, secret)
                .compact();
    }

    //解析JWT
    public Claims getClaimByToken(String jwt) {

        try {
            return Jwts.parser()
                    .setSigningKey(secret)
                    .parseClaimsJws(jwt)
                    .getBody();
        } catch (Exception e) {
            return null;
        }
    }

    //JWT是否过期
    public boolean isTokenExpired(Claims claims) {
        return claims.getExpiration().before(new Date());
    }
}

JWTAuthenticationFilter

public class JWTAuthenticationFilter extends BasicAuthenticationFilter {

    @Autowired
    private UserService userService;

    @Autowired
    private JwtUtil jwtUtil;

    @Autowired
    private UserDetailsServiceImpl userDetailsService;

    public JWTAuthenticationFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
    }

    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {

        String jwt = request.getHeader(jwtUtil.getHeader());
        if (StrUtil.isBlankOrUndefined(jwt)) {
            chain.doFilter(request, response);
            return;
        }
        Claims claim = jwtUtil.getClaimByToken(jwt);
        if (claim == null) {
            throw new JwtException("token异常");
        }
        if (jwtUtil.isTokenExpired(claim)) {
            throw new JwtException("token已过期");
        }
        String username = claim.getSubject();
        //获取用户的权限等信息

        User user = userService.getByUsername(username);
        List<GrantedAuthority> userAuthority = userDetailsService.getUserAuthority(user.getId());
        UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, null, userAuthority);

        System.out.println("token->" + token);

        SecurityContextHolder.getContext().setAuthentication(token);
        chain.doFilter(request, response);
    }

}

ok大功告成 使用postman试试效果

admin用户拥有admin和normal角色,test用户拥有normal角色

在Controller中分配接口权限

//  如果使用 @PreAuthorize("hasRole('ROLE_ADMIN')")需要在类的头部加上@EnableGlobalMethodSecurity(prePostEnabled = true) //打开权限验证

@RestController
@RequestMapping("/user")
@EnableGlobalMethodSecurity(prePostEnabled = true)  //打开权限验证
public class UserController {

    @Autowired
    private UserService userService;

    @PreAuthorize("hasRole('admin')")
    @GetMapping("/admin")
    public String hello() {
        return "hello admin";
    }

    @PreAuthorize("hasRole('normal')")
    @GetMapping("/test")
    public String test() {
        return "hello test";
    }

    @PreAuthorize("hasRole('admin')")
    @GetMapping("/list")
    public Result list() {
        return ResultFactory.successful(userService.list());
    }

}

首先使用admin用户登录

在这里插入图片描述

在Header中有Authorization,也就是我们需要的token

在这里插入图片描述
在这里插入图片描述

接着使用admin用户的token去访问其他接口

在这里插入图片描述

在这里插入图片描述

admin用户都可以访问

接着使用test用户登录

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

使用test用户去访问其他接口

在这里插入图片描述

在这里插入图片描述

因为test用户只有normal角色,所以只能访问test接口,admin接口权限不足

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-07-30 12:36:58  更:2021-07-30 12:37:47 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年4日历 -2024/4/28 15:30:30-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码