小编Fly*_*eep的帖子

比较SQLAlchemy对象实例以获得属性的等同性

我的Flask-Restful应用程序有许多"对象".在应用程序的第一个版本中,这些是没有行为的简单数据结构,实现为Dicts或Dicts列表.

这些"对象"的属性可以改变.我使用生成器函数来跟踪更改,然后通过服务器发送事件(SSE)警告Web客户端.这通过维护要跟踪的对象的"旧"副本并将其与最新状态进行比较来工作.

在应用程序的下一个版本中,我使用SQLAlchemy从SQLite数据库填充"对象".这些对象现在实现为SQLAlchemy声明性类或此类的列表.

为了比较基于属性相等的"旧"和"新"实例,我只需要__eq__为我的SQLAlchemy对象添加一个覆盖.即,当属性具有相同的值时,实例被认为是相等/不变的.(我已在此问题的底部发布了示例代码).

从技术上讲,这是有效的,但引起了一些建筑警钟:我是否朝错误的方向航行?

a)如果我添加__eq____ne__覆盖SQAlchemy对象,当我后来想要将对象重新保存回数据库时,这是否会导致SQLAlchemy出现问题?

b)SQLAlchemy对象应该在我的应用程序中达到多远:是否有"pythonic最佳实践"?即,使用与DB持久性无关的业务逻辑/行为(例如跟踪更改)扩展SQLAlchemy对象是否正常/正常; 或者它们应该仅用作数据库和服务器之间的简单DTO,还有其他对象中的业务逻辑?

注意:我很清楚,通过REST apis和SSE呈现给客户端的数据应该从Web服务器和数据库中的实现细节中抽象出来,因此这不是这个问题的一部分.

sqlalchemy id equal vs reference equality https://codereview.stackexchange.com/questions/93511/data-transfer-objects-vs-entities-in-java-rest-server-application http://www.mehdi-khalili.com/ORM-反模式部分-4-持久性域模型/

class EqualityMixin(object):
# extended from the concept in :
# https://stackoverflow.com/questions/390250/elegant-ways-to-support-equivalence-equality-in-python-classes

    def __eq__(self, other):
        classes_match = isinstance(other, self.__class__)
        a, b = deepcopy(self.__dict__), deepcopy(other.__dict__)
        #compare based on equality our attributes, ignoring SQLAlchemy internal stuff
        a.pop('_sa_instance_state', None)
        b.pop('_sa_instance_state', None)
        attrs_match = (a == b)
        return classes_match and attrs_match

    def __ne__(self, other):
        return not self.__eq__(other)
Run Code Online (Sandbox Code Playgroud)

python sqlalchemy

22
推荐指数
1
解决办法
3276
查看次数

Byte-Buddy:方法拦截 InvoiceHandler 与 MethodDelegation 到 GeneralInterceptor

我使用 Byte-Buddy 动态生成 Java 接口方法的实现,并将对这些方法的调用委托给现有代理对象的单个方法。

第一个版本的灵感来自如何使用 ByteBuddy 创建动态代理

它使用反射InvocationHandler

即具体代理类:

  • 实现接口InvocationHandler
  • 覆盖该方法invoke()

这很好用。

然后重新阅读Github 上的 Byte-Buddy 自述文件,MethodDelegation我发现了使用“GeneralInterceptor”的替代版本。

即具体代理类:

  • 有一个用注释标记的方法RuntimeType

这也很好用!

下面的代码片段演示了这两种技术。

Class<? extends Object> clazz = new ByteBuddy()
    .subclass(serviceSuperClass)
    .name(className) 
    // use a Reflection InvocationHander for the methods of serviceInterfaceOne
    .implement(serviceInterfaceOne)
    .defineField(invocationHandler, MyProxy.class, Visibility.PUBLIC)
    .method(isDeclaredBy(serviceInterfaceOne))
    .intercept(InvocationHandlerAdapter.toField(invocationHandler))
    // use a Byte-Buddy "GeneralInterceptor" for the methods of serviceInterfaceTwo
    .implement(serviceInterfaceTwo)
    .defineField(generalInterceptor, MyProxy.class, Visibility.PUBLIC)
    .method(isDeclaredBy(serviceInterfaceTwo))
    .intercept(MethodDelegation.toField(generalInterceptor))
    //
    .make ()
    .load(classLoader)
    .getLoaded();
Run Code Online (Sandbox Code Playgroud)
public class MyProxy implements …
Run Code Online (Sandbox Code Playgroud)

java byte-buddy

5
推荐指数
1
解决办法
1350
查看次数

Java GSS-API服务票证未使用Java保存在凭据高速缓存中

我使用GSS-API创建了2个演示Kerberos客户端.一个在Python3中,第二个在Java中.两个客户端似乎大致相同,并且两者都"起作用",因为我获得了我的Java GSS-API服务主体接受的服务票证.

但是在测试时我注意到Python客户端将服务票据保存在kerberos凭证缓存中,而Java客户端似乎没有保存票证.

我使用"klist"来查看凭证缓存的内容.

我的客户使用FreeIPA作为Kerberos环境在Lubuntu 17.04虚拟机上运行.我正在使用OpenJDK 8 u131.

问题1: Java GSS-API是否不保存凭证缓存的服务票证?或者我可以更改我的代码吗?

问题2:服务票据未保存到缓存这一事实是否有任何缺点?

我的假设是缓存的服务票据减少了与KDC的交互,但评论了如何使用Windows Java客户端保存Kerberos服务票证?建议事实并非如此,但是这个Microsoft技术说明"每次想要访问这个特定服务器时,客户端都不需要返回KDC".

问题3:来自python客户端的缓存服务票证在几分钟后消失 - 在到期日之前很久.是什么导致他们消失?

Python代码

#!/usr/bin/python3.5

import gssapi
from io import BytesIO

server_name = 'HTTP/app-srv.acme.com@ACME.COM'
service_name = gssapi.Name(server_name)

client_ctx = gssapi.SecurityContext(name=service_name, usage='initiate')
initial_client_token = client_ctx.step()
Run Code Online (Sandbox Code Playgroud)

Java代码

System.setProperty("java.security.krb5.conf","/etc/krb5.conf");
System.setProperty("javax.security.auth.useSubjectCredsOnly","false");

GSSManager manager = GSSManager.getInstance();
GSSName clientName;
GSSContext context = null;

//try catch removed for brevity
GSSName serverName = 
      manager.createName("HTTP/app-srv.acme.com@ACME.COM", null);

Oid krb5Oid = new Oid("1.2.840.113554.1.2.2");

//use default credentials
context = manager.createContext(serverName,
    krb5Oid,
    null, …
Run Code Online (Sandbox Code Playgroud)

java kerberos gssapi

4
推荐指数
1
解决办法
1722
查看次数

标签 统计

java ×2

byte-buddy ×1

gssapi ×1

kerberos ×1

python ×1

sqlalchemy ×1