Java 使用JAAS登录模块注销
这个问题比预期的要长一点。下面是一个类似的链接(第三篇文章),我没有找到令人满意的答案 我正在尝试使用JAAS登录模块注销。以下是该项目的简要结构:Java 使用JAAS登录模块注销,java,spring-boot,rest,jaas,Java,Spring Boot,Rest,Jaas,这个问题比预期的要长一点。下面是一个类似的链接(第三篇文章),我没有找到令人满意的答案 我正在尝试使用JAAS登录模块注销。以下是该项目的简要结构: LoginService负责在用户想要登录时实例化LoginContext: @Service public class LoginService { public UserDTO getUserDTOFrom(Credentials credentials) { try { Lo
LoginService
负责在用户想要登录时实例化LoginContext
:
@Service
public class LoginService {
public UserDTO getUserDTOFrom(Credentials credentials) {
try {
LoginContext loginContext = new LoginContext("Login", new JAASCallbackHandler(credentials));
loginContext.login();
// construct UserDTO object.
} catch (LoginException e) {
LOGGER.error("Login Exception: {}", e.getMessage());
// construct UserDTO object.
}
// return UserDTO object.
}
LoginController
调用该方法:
@RestController
@RequestMapping("/login")
public class LoginController {
private final LoginService loginService;
@Autowired
public LoginController(LoginService loginService) {
this.loginService = loginService;
}
@PostMapping
public ResponseEntity<UserDTO> getUserDTOFrom(@Valid @RequestBody Credentials credentials) {
UserDTO userDTO = loginService.getUserDTOFrom(userForm);
// return response that depends on outcome in the login service
}
}
我没有LogoutService
中的LoginContext
,无法完全清除先前已验证的主题
我试图创建一个单例bean,以获得与LoginContext
相同的实例:
@Configuration
public class LoginContextBean {
@Lazy
@Bean
public LoginContext getLoginContext(Credentials credentials) throws LoginException {
System.setProperty("java.security.auth.login.config", "resources/configuration/jaas.config");
return new LoginContext("Login", new JAASCallbackHandler(credentials));
}
}
@Service
public class LoginService {
private final ObjectProvider<LoginContext> loginContextProvider;
@Autowired
public LoginService(ObjectProvider<LoginContext> loginContextProvider) {
this.loginContextProvider = loginContextProvider;
}
public UserDTO getUserDTOFrom(Credentials credentials) {
try {
LoginContext loginContext = loginContextProvider.getObject(credentials);
loginContext.login();
// construct UserDTO object.
} catch (LoginException e) {
LOGGER.error("Login Exception: {}", e.getMessage());
// construct UserDTO object.
}
// return UserDTO object.
}
}
@Service
public class LogoutService {
private final ObjectProvider<LoginContext> loginContextProvider;
@Autowired
public LogoutService(ObjectProvider<LoginContext> loginContextProvider) {
this.loginContextProvider = loginContextProvider;
}
public void performLogout() {
LoginContext loginContext = loginContextProvider.getObject();
try {
loginContext.logout();
} catch (LoginException e) {
LOGGER.error("Failed to logout: {}.", e.getMessage());
}
}
}
当一个用户想要注销时,我想得到先前创建的LoginContext
,但当另一个用户尝试登录时,我想创建一个新的。
请注意,我没有使用Spring Security
编辑:
其中一个想法是使用一个单例来保存与特定用户关联的登录上下文集。然后在用户注销时调用并销毁它们。此类
集合的密钥可以是JWT令牌或用户id。经过进一步思考,我认为用户可能有多个会话,在这种情况下,作为密钥的用户id将无法发挥作用。第二个选项是JWT令牌,但有一种情况是,未来的中间件将在到期时发布一个新的JWT令牌,那么我的集将无法返回有效的登录上下文。经过一些研究,我的团队认为JAAS不适合我们的需要。我们没有使用它所提供的完整功能,它束缚了我们的手脚,而不是平滑开发过程
如果您会遇到类似问题,以下是一个解释:
我们正在使用支持JAAS的WebSphere8.5.5。可以注销,但价格将限制在应用服务器上。考虑到我们的计划是从WebSphere迁移,此实现不是一个选项。
指向其中一个指南的链接存在
未来有两种选择:
用Spring Security包装它,因为它提供了李>
完全依靠Spring Security的
功能
@Configuration
public class LoginContextBean {
@Lazy
@Bean
public LoginContext getLoginContext(Credentials credentials) throws LoginException {
System.setProperty("java.security.auth.login.config", "resources/configuration/jaas.config");
return new LoginContext("Login", new JAASCallbackHandler(credentials));
}
}
@Service
public class LoginService {
private final ObjectProvider<LoginContext> loginContextProvider;
@Autowired
public LoginService(ObjectProvider<LoginContext> loginContextProvider) {
this.loginContextProvider = loginContextProvider;
}
public UserDTO getUserDTOFrom(Credentials credentials) {
try {
LoginContext loginContext = loginContextProvider.getObject(credentials);
loginContext.login();
// construct UserDTO object.
} catch (LoginException e) {
LOGGER.error("Login Exception: {}", e.getMessage());
// construct UserDTO object.
}
// return UserDTO object.
}
}
@Service
public class LogoutService {
private final ObjectProvider<LoginContext> loginContextProvider;
@Autowired
public LogoutService(ObjectProvider<LoginContext> loginContextProvider) {
this.loginContextProvider = loginContextProvider;
}
public void performLogout() {
LoginContext loginContext = loginContextProvider.getObject();
try {
loginContext.logout();
} catch (LoginException e) {
LOGGER.error("Failed to logout: {}.", e.getMessage());
}
}
}
@RestController
@RequestMapping("/logout")
public class LogoutController {
private final LogoutService logoutService;
@Autowired
public LogoutController(LogoutService logoutService) {
this.logoutService = logoutService;
}
@DeleteMapping
public ResponseEntity<Void> deleteJwt(@CookieValue("jwt_cookie") String jwtToken, HttpServletRequest request) throws ServletException {
request.getSession().invalidate(); // logout() is not called.
request.logout(); // logout() is not called.
return getResponse();
}
}