SpringSecurity中授权时fastjson序列化问题

2023-11-12

最近在复习Spring Security,复习的鉴权的时候出现问题。26.封装权限信息_哔哩哔哩_bilibili

如果是从B站中看到,直接说问题可能出现的原因:可能是private List<String> authorities;中的权限信息命名不规范,去掉get,A变小写。如果要细看原因请往下看。

 下图是代码中aaaaa是我测试的权限信息集合,故意命名写的不规范,才知道原因。

问题场景:使用Spring Security模拟授权的时候,手动存入几个权限信息,然后正确的访问时出现了问题。

重要的事情放前面说:如果不配置权限集合如果不加@JSONField(serialize = false)注解,解析的时候会报错。

 UserDetailServiceImpl.java   UserDetailsService实现类

@Service
public class UserDetailServiceImpl implements UserDetailsService {


    @Autowired
    private UserMapper userMapper;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //查询用户信息

        LambdaQueryWrapper<User> queryChainWrap = new LambdaQueryWrapper<>();
        queryChainWrap.eq(!Objects.isNull(username), User::getUserName, username);
        User user = userMapper.selectOne(queryChainWrap);
        // 如果没有查询到用户就抛出异常
        if (Objects.isNull(user)) {
            throw new RuntimeException("用户名或密码错误");
        }

        //TODO 查询对应的权限信息
        ArrayList<String> list = new ArrayList<>(Arrays.asList("test", "admin"));

        // 把数据封装成UserDetails返回
        return new LoginUser(user, list);
//        return new LoginUser(user);
    }
}

LoginServiceImpl.java   自定义登录接口实现类

@Service
public class LoginServiceImpl implements LoginService {

    @Autowired
    private AuthenticationManager authenticationManager;


    @Autowired
    private RedisCache redisCache;

    @Override
    public ResponseResult login(User user) throws Exception {
        //AuthenticationManager authenticate进行用户认证
        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
                new UsernamePasswordAuthenticationToken(user.getUserName(), user.getPassword());
        Authentication authenticate = authenticationManager.authenticate(usernamePasswordAuthenticationToken);
//        authenticate.getPrincipal()
        // 如果认证没有通过,给出对应的提示
        if (Objects.isNull(authenticate)) {
            throw new RuntimeException("登录失败");
        }
        // 如果认证通过了,使用userid生成jwt jwt存入ResponseResult返回
        LoginUser loginUser = (LoginUser) authenticate.getPrincipal();
        String userId = loginUser.getUser().getId().toString();
        String jwt = JwtUtil.createJWT(userId);

        Map<String, String> map = new HashMap<>();
        map.put("token", jwt);
        // 把完整的用户信息存入redis userid作为key
        redisCache.setCacheObject(SystemConstants.LOGIN_TOKEN_PREFIX + userId, loginUser);
        return new ResponseResult(200, "登录成功", map);
    }

    @Override
    public ResponseResult logout() {
        // 获取SecurityContextHolder中的用户id
        UsernamePasswordAuthenticationToken authentication = (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();

        Long userId = loginUser.getUser().getId();
        // 删除redis中的值
        redisCache.deleteObject(SystemConstants.LOGIN_TOKEN_PREFIX + userId);
        return new ResponseResult(200, "注销成功");
    }
}

JwtAuthenticationTokenFilter.java   自定义过滤器

@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {


    @Autowired
    private RedisCache redisCache;

    @Autowired
    private AuthenticationManager authenticationManager;

    @SneakyThrows(value = {RuntimeException.class, ArrayIndexOutOfBoundsException.class, Exception.class})
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        // 获取token
        String token = request.getHeader("token");
        // token为内容为空或者不以login:开头直接放行
        if (!StringUtils.hasText(token)) {
            // 放行
            filterChain.doFilter(request, response);
            return;
        }
        // 解析token获取其中的userId
        String userId;
        try {
            userId = JwtUtil.parseJWT(token).getSubject();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("token非法");
        }
        // 从redis中获取用户信息
        String redisKey = SystemConstants.LOGIN_TOKEN_PREFIX + userId;
        LoginUser loginUser = redisCache.getCacheObject(redisKey);
        if (Objects.isNull(loginUser)) {
            throw new RuntimeException("用户未登录");
        }
        // 存入SecurityContextHolder
        // TODO 获取权限信息封装到Authentication
        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
                new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities());
        // 这里不知道为什么加这句,导致进行验证,走了后续过滤器,但是我发送的测试请求是带token的get请求,
        // 但是我的数据是从redis中获取,密码是加密后的,导致二次加密后,密码不一致
//        Authentication authenticate = authenticationManager.authenticate(usernamePasswordAuthenticationToken);

        SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
        // 放行
        filterChain.doFilter(request, response);
    }
}

 待测试的Controller

 LoginUser.java   UserDetails实现类

@Data
@NoArgsConstructor
public class LoginUser implements UserDetails {

    private User user;

    private List<String> permission;


    @JSONField(serialize = false)
//    @JsonIgnore
//    @JsonIgnoreProperties
    private List<GrantedAuthority> aaaaa;

//    @JSONField(serialize = false)
//    private List<String> authorities;

    public LoginUser(User user, List<String> permission) {
        this.user = user;
        this.permission = permission;
    }

    public LoginUser(User user) {
        this.user = user;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        // 把permission中String类型的去啊年信息封装成SimpleGrantedAuthority对象
        if (Objects.isNull(aaaaa)) {
            synchronized (this) {
                if (Objects.isNull(aaaaa)) {
                    aaaaa
                            = permission.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList());
                }
            }
        }
        return aaaaa;
//        ArrayList<GrantedAuthority> list = new ArrayList<>();
//        list.add(new SimpleGrantedAuthority("Powerveil"));
//        return list;
    }

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

    @Override
    public String getUsername() {
        return user.getUserName();
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }
}

 直接看结果

 没有任何输出

看一下idea的console

2023-06-18 18:46:34.557 ERROR 21216 --- [nio-8080-exec-4] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception

com.alibaba.fastjson.JSONException: autoType is not support. org.springframework.security.core.authority.SimpleGrantedAuthority
	at com.alibaba.fastjson.parser.ParserConfig.checkAutoType(ParserConfig.java:830) ~[fastjson-1.2.33.jar:na]
	at com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer.deserialze(JavaBeanDeserializer.java:596) ~[fastjson-1.2.33.jar:na]
	at com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer.deserialze(JavaBeanDeserializer.java:226) ~[fastjson-1.2.33.jar:na]
	at com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer.deserialze(JavaBeanDeserializer.java:222) ~[fastjson-1.2.33.jar:na]
	at com.alibaba.fastjson.parser.DefaultJSONParser.parseArray(DefaultJSONParser.java:716) ~[fastjson-1.2.33.jar:na]
	at com.alibaba.fastjson.serializer.CollectionCodec.deserialze(CollectionCodec.java:120) ~[fastjson-1.2.33.jar:na]
	at com.alibaba.fastjson.parser.deserializer.DefaultFieldDeserializer.parseField(DefaultFieldDeserializer.java:78) ~[fastjson-1.2.33.jar:na]
	at com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer.parseField(JavaBeanDeserializer.java:911) ~[fastjson-1.2.33.jar:na]
	at com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer.deserialze(JavaBeanDeserializer.java:656) ~[fastjson-1.2.33.jar:na]
	at com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer.deserialze(JavaBeanDeserializer.java:226) ~[fastjson-1.2.33.jar:na]
	at com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer.deserialze(JavaBeanDeserializer.java:222) ~[fastjson-1.2.33.jar:na]
	at com.alibaba.fastjson.parser.DefaultJSONParser.parseObject(DefaultJSONParser.java:357) ~[fastjson-1.2.33.jar:na]
	at com.alibaba.fastjson.parser.DefaultJSONParser.parse(DefaultJSONParser.java:1325) ~[fastjson-1.2.33.jar:na]
	at com.alibaba.fastjson.parser.deserializer.JavaObjectDeserializer.deserialze(JavaObjectDeserializer.java:45) ~[fastjson-1.2.33.jar:na]
	at com.alibaba.fastjson.parser.DefaultJSONParser.parseObject(DefaultJSONParser.java:630) ~[fastjson-1.2.33.jar:na]
	at com.alibaba.fastjson.JSON.parseObject(JSON.java:354) ~[fastjson-1.2.33.jar:na]
	at com.alibaba.fastjson.JSON.parseObject(JSON.java:258) ~[fastjson-1.2.33.jar:na]
	at com.alibaba.fastjson.JSON.parseObject(JSON.java:471) ~[fastjson-1.2.33.jar:na]
	at com.powerveil.utils.FastJsonRedisSerializer.deserialize(FastJsonRedisSerializer.java:56) ~[classes/:na]
	at org.springframework.data.redis.core.AbstractOperations.deserializeValue(AbstractOperations.java:335) ~[spring-data-redis-2.5.1.jar:2.5.1]
	at org.springframework.data.redis.core.AbstractOperations$ValueDeserializingRedisCallback.doInRedis(AbstractOperations.java:61) ~[spring-data-redis-2.5.1.jar:2.5.1]
	at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:222) ~[spring-data-redis-2.5.1.jar:2.5.1]
	at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:189) ~[spring-data-redis-2.5.1.jar:2.5.1]
	at org.springframework.data.redis.core.AbstractOperations.execute(AbstractOperations.java:96) ~[spring-data-redis-2.5.1.jar:2.5.1]
	at org.springframework.data.redis.core.DefaultValueOperations.get(DefaultValueOperations.java:53) ~[spring-data-redis-2.5.1.jar:2.5.1]
	at com.powerveil.utils.RedisCache.getCacheObject(RedisCache.java:78) ~[classes/:na]
	at com.powerveil.filter.JwtAuthenticationTokenFilter.doFilterInternal(JwtAuthenticationTokenFilter.java:61) ~[classes/:na]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.7.jar:5.3.7]
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.5.0.jar:5.5.0]
	at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:103) ~[spring-security-web-5.5.0.jar:5.5.0]
	at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:89) ~[spring-security-web-5.5.0.jar:5.5.0]
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.5.0.jar:5.5.0]
	at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90) ~[spring-security-web-5.5.0.jar:5.5.0]
	at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75) ~[spring-security-web-5.5.0.jar:5.5.0]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.7.jar:5.3.7]
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.5.0.jar:5.5.0]
	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:110) ~[spring-security-web-5.5.0.jar:5.5.0]
	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80) ~[spring-security-web-5.5.0.jar:5.5.0]
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.5.0.jar:5.5.0]
	at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:55) ~[spring-security-web-5.5.0.jar:5.5.0]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.7.jar:5.3.7]
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.5.0.jar:5.5.0]
	at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:211) ~[spring-security-web-5.5.0.jar:5.5.0]
	at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:183) ~[spring-security-web-5.5.0.jar:5.5.0]
	at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358) ~[spring-web-5.3.7.jar:5.3.7]
	at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271) ~[spring-web-5.3.7.jar:5.3.7]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.7.jar:5.3.7]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.7.jar:5.3.7]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.7.jar:5.3.7]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.7.jar:5.3.7]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.7.jar:5.3.7]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.7.jar:5.3.7]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) [tomcat-embed-core-9.0.46.jar:9.0.46]
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542) [tomcat-embed-core-9.0.46.jar:9.0.46]
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143) [tomcat-embed-core-9.0.46.jar:9.0.46]
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) [tomcat-embed-core-9.0.46.jar:9.0.46]
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) [tomcat-embed-core-9.0.46.jar:9.0.46]
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357) [tomcat-embed-core-9.0.46.jar:9.0.46]
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374) [tomcat-embed-core-9.0.46.jar:9.0.46]
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) [tomcat-embed-core-9.0.46.jar:9.0.46]
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:893) [tomcat-embed-core-9.0.46.jar:9.0.46]
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1707) [tomcat-embed-core-9.0.46.jar:9.0.46]
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.46.jar:9.0.46]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_321]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_321]
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.46.jar:9.0.46]
	at java.lang.Thread.run(Thread.java:750) [na:1.8.0_321]

错误日志多不要害怕

 autoType is not support   不支持自动类型

看下面的错误

RedisCache.java是一个自定义的Redis工具类

原来是redis取出数据出现问题,看一下redis中存储的数据。

{
  "@type": "com.powerveil.domain.LoginUser",
  "accountNonExpired": true,
  "accountNonLocked": true,
  "authorities": [
    {
      "@type": "org.springframework.security.core.authority.SimpleGrantedAuthority",
      "authority": "test"
    },
    {
      "@type": "org.springframework.security.core.authority.SimpleGrantedAuthority",
      "authority": "admin"
    }
  ],
  "credentialsNonExpired": true,
  "enabled": true,
  "password": "$2a$10$4MzpJkpyo2gywu5B/b6zEO3gfyYqcEN.6PG5wEpcb9nASzPddq7fu",
  "permission": [
    "test",
    "admin"
  ],
  "user": {
    "delFlag": 0,
    "email": "zcuishuai@yeah.net",
    "id": 1,
    "nickName": "Powerveil",
    "password": "$2a$10$4MzpJkpyo2gywu5B/b6zEO3gfyYqcEN.6PG5wEpcb9nASzPddq7fu",
    "phonenumber": "123456789",
    "sex": "0",
    "status": "0",
    "userName": "Powerveil",
    "userType": "1"
  },
  "username": "Powerveil"
}

看到redis数据,怎么这么多字段

我自定义了只有三个字段

user

permission

aaaaa

 user,permisssion都看到出来,但是我的aaaaa怎么没有了,正常,因为使用了@JSONField(serialize = false)注解,不会写入redis中。

postman返回的结果

上面是我第一次遇到的情况,以下是其他测试情况,看完你就知道原因了。

2.将getAuthorities方法的返回值设为null其他不变。

redis中的结果 

发现authorities消失了

数据可以正常解析

但是结果403,但是也正常,因为鉴权的方法的返回值是null。

3.添加authorities字段

 方法正常重写

查看redis数据

发现authorities字段生成

redis数据解析错误

 postman返回的结果

4.给authorities字段加上@JSONField(serialize = false)注解

查看redis数据,发现authorities字段消失

可以获取正常解析redis数据到loginUser

 可以输出结果

我推测是Spring Security会判断authorities字段是否存在如果getAuthorities方法返回值为null或者该字段加上@JSONField(serialize = false),则不会存入redis中。如下图

其他情况会存入redis中。如下图

但是我们最后要做的是鉴权的时候,方法的返回值不能是null呀。所以只有给authorities字段加上@JSONField(serialize = false)注解才能解决问题。现在突然醒悟了,那我们还要aaaaa这个字段干什么,直接加上authorities字段再给它配个注解,方法里面都写authorities不就解决问题了?是的,确实是这样,因为Spring Security检查的是authorities字段加上@JSONField(serialize = false)注解才会判断要不要写入redis。这个aaaaa这个字段确实多余。

看到这里,大家可能知道问题的原因了,是因为没有定义authorities字段(不能写错!!!)。

查看效果

redis中的数据

 redis解析正常

postman返回数据正常

思考:LoginUser类中字段只写了三个,而且一个加入注解忽略写入redis,为什么还有这么多其他字段?

看一下LoginUser的方法

像不像方法与字段像对应

这样就清晰了,getAuthorities方法应该也可以对应一个字段authorites,如果返回值不为null那个就会有生成字段。存入redis的时候发现这个生成的authorites字段,因为是生成的,没有配置@JSONField(serialize = false)注解,所以会直接存入redis。取出的时候发现没有这个字段,就会报错,就算有这个字段,也解析不出来(重要的事情在文章场景描述的地方)。

这个提醒了我们什么?要规范命名(手动狗头)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SpringSecurity中授权时fastjson序列化问题 的相关文章

  • 如何为最终用户方便地启动Java GUI程序

    用户想要从以下位置启动 Java GUI 应用程序Windows 以及一些额外的 JVM 参数 例如 javaw Djava util logging config file logging properties jar MyGUI jar
  • Spring Batch 多线程 - 如何使每个线程读取唯一的记录?

    这个问题在很多论坛上都被问过很多次了 但我没有看到适合我的答案 我正在尝试在我的 Spring Batch 实现中实现多线程步骤 有一个包含 100k 条记录的临时表 想要在 10 个线程中处理它 每个线程的提交间隔为 300 因此在任何时
  • 如何默认将 Maven 插件附加到阶段?

    我有一个 Maven 插件应该在编译阶段运行 所以在项目中consumes我的插件 我必须做这样的事情
  • 在画布上绘图

    我正在编写一个 Android 应用程序 它可以在视图的 onDraw 事件上直接绘制到画布上 我正在绘制一些涉及单独绘制每个像素的东西 为此我使用类似的东西 for int x 0 x lt xMax x for int y 0 y lt
  • Java - 将节点添加到列表的末尾?

    这是我所拥有的 public class Node Object data Node next Node Object data Node next this data data this next next public Object g
  • 给定两个 SSH2 密钥,我如何检查它们是否属于 Java 中的同一密钥对?

    我正在尝试找到一种方法来验证两个 SSH2 密钥 一个私有密钥和一个公共密钥 是否属于同一密钥对 我用过JSch http www jcraft com jsch 用于加载和解析私钥 更新 可以显示如何从私钥 SSH2 RSA 重新生成公钥
  • Android:捕获的图像未显示在图库中(媒体扫描仪意图不起作用)

    我遇到以下问题 我正在开发一个应用程序 用户可以在其中拍照 附加到帖子中 并将图片保存到外部存储中 我希望这张照片也显示在图片库中 并且我正在使用媒体扫描仪意图 但它似乎不起作用 我在编写代码时遵循官方的Android开发人员指南 所以我不
  • Spark 1.3.1 上的 Apache Phoenix(4.3.1 和 4.4.0-HBase-0.98)ClassNotFoundException

    我正在尝试通过 Spark 连接到 Phoenix 并且在通过 JDBC 驱动程序打开连接时不断收到以下异常 为简洁起见 下面是完整的堆栈跟踪 Caused by java lang ClassNotFoundException org a
  • JavaMail 只获取新邮件

    我想知道是否有一种方法可以在javamail中只获取新消息 例如 在初始加载时 获取收件箱中的所有消息并存储它们 然后 每当应用程序再次加载时 仅获取新消息 而不是再次重新加载它们 javamail 可以做到这一点吗 它是如何工作的 一些背
  • 磁模拟

    假设我在 n m 像素的 2D 表面上有 p 个节点 我希望这些节点相互吸引 使得它们相距越远吸引力就越强 但是 如果两个节点之间的距离 比如 d A B 小于某个阈值 比如 k 那么它们就会开始排斥 谁能让我开始编写一些关于如何随时间更新
  • 路径中 File.separator 和斜杠之间的区别

    使用有什么区别File separator和一个正常的 在 Java 路径字符串中 与双反斜杠相反 平台独立性似乎不是原因 因为两个版本都可以在 Windows 和 Unix 下运行 public class SlashTest Test
  • Mockito when().thenReturn 不必要地调用该方法

    我正在研究继承的代码 我编写了一个应该捕获 NullPointerException 的测试 因为它试图从 null 对象调用方法 Test expected NullPointerException class public void c
  • 如何为俚语和表情符号构建正则表达式 (regex)

    我需要构建一个正则表达式来匹配俚语 即 lol lmao imo 等 和表情符号 即 P 等 我按照以下示例进行操作http www coderanch com t 497238 java java Regular Expression D
  • JRE 系统库 [WebSphere v6.1 JRE](未绑定)

    将项目导入 Eclipse 后 我的构建路径中出现以下错误 JRE System Library WebSphere v6 1 JRE unbound 谁知道怎么修它 右键单击项目 特性 gt Java 构建路径 gt 图书馆 gt JRE
  • Eclipse Java 远程调试器通过 VPN 速度极慢

    我有时被迫离开办公室工作 这意味着我需要通过 VPN 进入我的实验室 我注意到在这种情况下使用 Eclipse 进行远程调试速度非常慢 速度慢到调试器需要 5 7 分钟才能连接到远程 jvm 连接后 每次单步执行断点 行可能需要 20 30
  • Java执行器服务线程池[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 如果我使用 Executor 框架在
  • 在mockito中使用when进行模拟ContextLoader.getCurrentWebApplicationContext()调用。我该怎么做?

    我试图在使用 mockito 时模拟 ContextLoader getCurrentWebApplicationContext 调用 但它无法模拟 here is my source code Mock org springframewo
  • simpleframework,将空元素反序列化为空字符串而不是 null

    我使用简单框架 http simple sourceforge net http simple sourceforge net 在一个项目中满足我的序列化 反序列化需求 但在处理空 空字符串值时它不能按预期工作 好吧 至少不是我所期望的 如
  • 捕获的图像分辨率太大

    我在做什么 我允许用户捕获图像 将其存储到 SD 卡中并上传到服务器 但捕获图像的分辨率为宽度 4608 像素和高度 2592 像素 现在我想要什么 如何在不影响质量的情况下获得小分辨率图像 例如我可以获取或设置捕获的图像分辨率为原始图像分
  • 当我从 Netbeans 创建 Derby 数据库时,它存储在哪里?

    当我从 netbeans 创建 Derby 数据库时 它存储在哪里 如何将它与项目的其余部分合并到一个文件夹中 右键单击Databases gt JavaDB in the Service查看并选择Properties This will

随机推荐

  • 【java语法基础】常量与变量、数据类型,以及数据类型的转换

    常量 就是值永远不被改变的量 声明一个常量 需要用final关键字修饰 具体格式 final 常量类型 常量标识符 常量值 例如 final int PIE 18 注 在定义一个常量标识符时 所有的字符都要大写 如果常量标识符由多个单词组成
  • 用python实现数字图片识别神经网络--实现网络训练功能

    上节我们完成了神经网络基本框架的搭建 当时剩下了最重要的一个接口train 也就是通过读取数据自我学习 进而改进网络识别效率的功能尚未实现 从本节开始 我们着手实现该功能 自我训练过程分两步走 第一步是计算输入训练数据 给出网络的计算结果
  • git查看日志

    目录 引言 git查看该项目提交记录 查看指定条数的记录 显示提交的差异 提交的简略信息 按行显示提交信息 按照指定格式显示记录 指定文件的提交记录 指定字符串或函数的提交记录 示例 引言 有时需要对之前所做的一些修改查看记录 这里是查看g
  • STM32F407ZGT6控制舵机(采用高级定时器8)

    前言 32单片机给舵机供电不足 会出现不稳定的情况 舵机鬼畜 所以要外加电源给舵机供电 利用12v锂电池 通过稳压模块降压到5 5v 提供给舵机 稳压电路的gnd一定要接上32单片机的gnd 不共地虽然能供电但数据线无法传输数据 stm32
  • 以太坊ERC-20协议详解

    区块链学习 https github com xianfeng92 Love Ethereum ERC20是以太坊定义的一个 代币标准 https github com ethereum EIPs blob master EIPS eip
  • 计算机网络综合选择题

    计算机网络综合选择题 TCP IP体系结构中的TCP和IP所提供的服务分别为 A 运输层服务和网络层服务 B 运输层服务和应用层服务 C 链路层服务和网络层服务 D 网络层服务和运输层服务 答案 A 2 对于无序接收的滑动窗口协议 若序号位
  • JAVA中的异常处理机制

    JAVA中的异常处理机制 java异常处理中的关键字 try catch finally throw throws return try 检测代码块 在此代码块中一旦检测到异常就会自动跳转到相应的catch try 检测代码块 catch
  • 21_pre_access 阶段

    文章目录 限制每个客户端的并发连接数 limit conn 指令 示例配置 限制每个客户端的每秒处理请求数 limit req 指令 限制每个客户端的并发连接数 ngx http limit conn module 生效阶段 ngx htt
  • Java实现FTP的上传和下载!

    java实现连接FTP服务器 实现文件的上传和下载 一 FTP服务器 FTP服务器 File Transfer Protocol Server 是在互联网上提供文件存储和访问服务的计算机 它们依照FTP协议提供服务 FTP协议是一种专门用来
  • 一文简单了解RPMB

    不知道大家对于RPMB有所了解吗 最近在看这些存储介质的介绍的时候 在推荐里面看到了这个东西 又因为对安全本身就有所涉及学习 所以这里来看看这个东西 学习的内容都是来自前辈们的blog 会在文末附注 1 Flash是什么 关于存储的种类有很
  • 解决mysql忘记密码无法登陆问题

    当我们忘记mysql密码的时候我们不仅无法访问数据库 也无法修改密码 这是个很头疼的问题 下面是跳过用户验证登陆数据库的小技巧 第一步 打开我们安装mysql的目录 复制 D PhpStudy PHPTutorial MySQL bin 地
  • 同一端口有2个前端应用应该如何配置nginx.conf

    需求 业务系统中有2种完全不同角色 页面没有相同模块拆分成了2个应用A和B 但后端是同一个后端 部署的时候要求A和B在同一端口下 问 如何配置nginx 首先我们将A B前端包放到 opt app jhscf deploy html下 这样
  • 电脑如何打开虚拟化设置?

    当你开启Vmware中的虚拟机时 如果出现以上提示 说明你的虚拟化没有打开 在计算机中 虚拟化 英语 Virtualization 是一种资源管理技术 是将计算机的各种实体资源 如服务器 网络 内存及存储等 予以抽象 转换后呈现出来 打破实
  • R语言-随机前沿分析法--SFA

    3 1介绍 生产函数模型 lnqi x i b vi ui 随机生产前沿函数 qi 产出变量向量 x i 投入变量向量 b 变量参数估计 vi 统计噪声的对称随机误差 ui 无效效应 3 2度量技术效率的方法 SFA 参数 DEA 非参数
  • Fortran 90学习之旅(一)Visual Fortran 6.5 的安装与第一个例子

    转载请标明是引用于 http blog csdn net chenyujing1234 源码 http www rayfile com zh cn files e5f02f0a 8799 11e1 b6a2 0015c55db73d 高尔夫
  • Java 中封装JDBC连接到JDBCUtils工具类的详解

    博主前些天发现了一个巨牛的人工智能学习网站 通俗易懂 风趣幽默 忍不住也分享一下给大家 点击跳转到网站 前言 在JDBC操作中 获取连接和释放资源是经常使用到的 可以将其封装成到一个工具类JDBCUtils中 JDBCUtils中有两个方法
  • .numpy()、.item()、.cpu()、.clone()、.detach()及.data的使用 && tensor类型的转换

    文章目录 numpy item cpu clone detach 及 data的使用 item cpu numpy clone detach data data和 detach 不同点 Tensor类型的转换 numpy item cpu
  • STM32定时器中断

    目录 一 关于STM32定时器中断 1 定时器分类 2 通用定时器的功能特点 3 定时器中断的触发 4 定时时钟计算方法 二 CubeMX初始化配置 1 芯片选型 我们这里运用的STM32F103C8T6 编辑 2 时钟配置 3 TIM2中
  • 经纬恒润OTA仿真测试解决方案为汽车智能化发展保驾护航

    OTA技术是汽车实现完整网联化 智能化体验的基础 自被引用汽车以来 广受研发人员 市场用户的关注 近来 国家有关部门也陆续出台了相应政策 对汽车企业OTA技术的应用进行了约束和规范 因此 OTA技术在量产车型的应用落地 离不开完整的测试验证
  • SpringSecurity中授权时fastjson序列化问题

    最近在复习Spring Security 复习的鉴权的时候出现问题 26 封装权限信息 哔哩哔哩 bilibili 如果是从B站中看到 直接说问题可能出现的原因 可能是private List