我正在迁移一个用 Quarkus 制作的应用程序,并使用 Renarde 作为 UI。我在解决一些与登录表单有关的问题。表单在我使用的旧版 Renarde(3.0.1)上运行良好,但使用新版 Renarde(3.0.19),当我提交表单时,我只得到一个空白页。我试图在代码中设置一个断点,但它甚至没有到达方法。安全性是通过数据库实现的。我很困惑,我真的不知道该怎么做。有人能帮忙吗?为此,我创建了 2 个类
@Provider
@Priority(1)
public class AuthenticationFailedExceptionHandler implements ExceptionMapper<AuthenticationFailedException> {
@Override
public Response toResponse(AuthenticationFailedException exception) {
var removeCookie = new NewCookie.Builder("Authorization")
.value(null)
.path("/")
.domain(null)
.comment(null)
.maxAge(0)
.secure(false)
.httpOnly(true)
.build();
var uri = getURI(Security::login);
return temporaryRedirect(uri).cookie(removeCookie).build();
}
}
和
@ApplicationScoped
public class UserSecuritySetup implements RenardeUserProvider, RenardeOidcHandler {
@Inject RenardeSecurity security;
@Override
public RenardeUser findUser(final String tenantId, final String username) {
return User.findByUsername(username);
}
@Override
public void oidcSuccess(String tenantId, String authId) {
}
@Override
public void loginWithOidcSession(String tenantId, String authId) {
}
}
我的用户实现了 RenardUser
@Entity
@Table(name = "user")
public class User extends PanacheEntity implements RenardeUser {
@Column(name = "code", nullable = false) public String code;
@Column(name = "firstname", nullable = false) public String firstname;
@Column(name = "lastname", nullable = false) public String lastname;
@Column(name = "created_at") public Instant createdAt;
@ManyToOne(fetch = FetchType.EAGER, optional = false) @JoinColumn(name = "role_id", nullable = false) public Role role;
@ManyToOne(fetch = FetchType.LAZY, optional = false) @JoinColumn(name = "status_id", nullable = false) public Status status;
@JsonbTransient @OneToOne(mappedBy = "user") public Credentials credentials;
@OneToOne(mappedBy = "user") public UserPicture picture;
public static User findByCode(String code) {
return User.find("code", code).firstResult();
}
public static User findByUsername(String username) {
return User.find("credentials.username", username).firstResult();
}
@Override
public Set<String> roles() {
Set<String> roles = new HashSet<>();
roles.add(role.code);
return roles;
}
@Override
public String userId() {
return credentials.username;
}
@Override
public boolean registered() {
return true;
}
}
这是用于登录应用程序的类的样子
import com.dwitech.surveille.ui.control.util.Helper;
import com.dwitech.surveille.ui.entity.db.User;
import io.micrometer.core.instrument.MeterRegistry;
import io.quarkiverse.renarde.security.ControllerWithUser;
import io.quarkus.qute.CheckedTemplate;
import io.quarkus.qute.TemplateInstance;
import io.smallrye.common.annotation.Blocking;
import jakarta.inject.Inject;
import jakarta.transaction.Transactional;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.core.NewCookie;
import jakarta.ws.rs.core.Response;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.jboss.logging.Logger;
import org.jboss.resteasy.reactive.RestForm;
import org.mindrot.jbcrypt.BCrypt;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import static com.dwitech.surveille.ui.control.util.CurrentMethod.name;
import static io.quarkiverse.renarde.router.Router.getURI;
import static io.quarkus.elytron.security.common.BcryptUtil.matches;
import static org.jboss.logging.Logger.getLogger;
@Path("/security")
@Blocking
public class Security extends ControllerWithUser<User> {
private static final Logger LOGGER = getLogger(Security.class);
private final MeterRegistry registry;
@ConfigProperty(name = "quarkus.application.name") String applicationName;
@ConfigProperty(name = "quarkus.profile") String profile;
@Inject Helper helper;
@Inject Audit audit;
@Inject DashboardHelper dashboardHelper;
Security(MeterRegistry registry) {
this.registry = registry;
}
public TemplateInstance display_login() {
return sign_in();
}
public TemplateInstance display_change_password(User user) {
return settings()
.data("picture", helper.getPictureAsBase64(user))
;
}
@POST
@Path("login")
public Response login(@RestForm String username, @RestForm String password) {
var action = name();
var user = User.findByUsername(username);
if (user == null || !matches(password, user.credentials.password) || !user.registered()) {
System.out.println("username --> Invalid username/password");
validation.addError("username", "Invalid username/password");
flash.flash("message", "Invalid user: "+username);
prepareForErrorRedirect();
audit.writeAuditLog("LGN", username, action, username, "Invalid username/password");
display_login();
}
var cookie = security.makeUserCookie(user);
String userRole = user.role.code;
System.out.println("userRole --> " + userRole);
audit.writeAuditLog("LGN", username, action, user.credentials.username, "logged in");
var template = dashboardHelper.getDashboard(user);
return Response.ok(template
.data("source", action)
.data("picture", helper.getPictureAsBase64(user))
.data("user", user)
).cookie(cookie).build();
}
@CheckedTemplate(requireTypeSafeExpressions = false)
public static class Templates {
public static native TemplateInstance sign_in();
}
}
这对我来说至关重要。有 2 个应用程序依赖它并且具有相同的行为。
问候并致谢。D.