mirror of
https://gitee.com/dromara/MaxKey.git
synced 2026-05-14 20:50:14 +08:00
rememberme
This commit is contained in:
@@ -32,6 +32,7 @@ public class AuthJwt implements Serializable {
|
||||
private String ticket;
|
||||
private String token;
|
||||
private String type = "Bearer";
|
||||
private String remeberMe;
|
||||
private String id;
|
||||
private String name;
|
||||
private String username;
|
||||
@@ -157,6 +158,13 @@ public class AuthJwt implements Serializable {
|
||||
this.passwordSetType = passwordSetType;
|
||||
}
|
||||
|
||||
public String getRemeberMe() {
|
||||
return remeberMe;
|
||||
}
|
||||
|
||||
public void setRemeberMe(String remeberMe) {
|
||||
this.remeberMe = remeberMe;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
|
||||
@@ -64,8 +64,6 @@ public class AuthJwtService {
|
||||
this.momentaryService = momentaryService;
|
||||
|
||||
this.hmac512Service = new HMAC512Service(authJwkConfig.getSecret());
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -69,11 +69,11 @@ public class Session implements Serializable{
|
||||
}
|
||||
|
||||
public String getFormattedId() {
|
||||
return id;
|
||||
return SESSION_PREFIX + id;
|
||||
}
|
||||
|
||||
public void setId(String ticketId) {
|
||||
this.id = ticketId;
|
||||
public void setId(String sessionId) {
|
||||
this.id = sessionId;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
package org.maxkey.authn.support.rememberme;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.util.Date;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.joda.time.DateTime;
|
||||
import org.maxkey.authn.SignPrincipal;
|
||||
import org.maxkey.authn.jwt.AuthJwtService;
|
||||
import org.maxkey.configuration.ApplicationConfig;
|
||||
import org.maxkey.crypto.jwt.HMAC512Service;
|
||||
import org.maxkey.entity.UserInfo;
|
||||
import org.maxkey.util.DateUtils;
|
||||
import org.maxkey.web.WebContext;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.security.core.Authentication;
|
||||
|
||||
import com.nimbusds.jwt.JWTClaimsSet;
|
||||
|
||||
public abstract class AbstractRemeberMeService {
|
||||
private static final Logger _logger = LoggerFactory.getLogger(AbstractRemeberMeService.class);
|
||||
|
||||
protected Integer validity = 7;
|
||||
|
||||
protected ApplicationConfig applicationConfig;
|
||||
|
||||
AuthJwtService authJwtService;
|
||||
|
||||
// follow function is for persist
|
||||
public abstract void save(RemeberMe remeberMe);
|
||||
|
||||
public abstract void update(RemeberMe remeberMe);
|
||||
|
||||
public abstract RemeberMe read(RemeberMe remeberMe);
|
||||
|
||||
public abstract void remove(String username);
|
||||
// end persist
|
||||
|
||||
public String createRemeberMe(Authentication authentication,
|
||||
HttpServletRequest request, HttpServletResponse response) {
|
||||
if (applicationConfig.getLoginConfig().isRemeberMe()) {
|
||||
SignPrincipal principal = ((SignPrincipal)authentication.getPrincipal());
|
||||
UserInfo userInfo = principal.getUserInfo();
|
||||
_logger.debug("Remeber Me ...");
|
||||
RemeberMe remeberMe = new RemeberMe();
|
||||
remeberMe.setId(WebContext.genId());
|
||||
remeberMe.setUserId(userInfo.getId());
|
||||
remeberMe.setUsername(userInfo.getUsername());
|
||||
remeberMe.setLastLoginTime(DateUtils.getCurrentDate());
|
||||
remeberMe.setExpirationTime(DateTime.now().plusDays(validity).toDate());
|
||||
save(remeberMe);
|
||||
_logger.debug("Remeber Me " + remeberMe);
|
||||
return genRemeberMe(remeberMe);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String updateRemeberMe(RemeberMe remeberMe) {
|
||||
remeberMe.setLastLoginTime(new Date());
|
||||
remeberMe.setExpirationTime(DateTime.now().plusDays(validity).toDate());
|
||||
update(remeberMe);
|
||||
_logger.debug("update Remeber Me " + remeberMe);
|
||||
|
||||
return genRemeberMe(remeberMe);
|
||||
}
|
||||
|
||||
public boolean removeRemeberMe(HttpServletResponse response,UserInfo currentUser) {
|
||||
remove(currentUser.getUsername());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public RemeberMe resolve(String rememberMeToken) throws ParseException {
|
||||
JWTClaimsSet claims = authJwtService.resolve(rememberMeToken);
|
||||
RemeberMe remeberMe = new RemeberMe();
|
||||
remeberMe.setId(claims.getJWTID());
|
||||
remeberMe.setUsername(claims.getSubject());
|
||||
return read(remeberMe);
|
||||
}
|
||||
|
||||
public String genRemeberMe(RemeberMe remeberMe ) {
|
||||
_logger.debug("expiration Time : {}" , remeberMe.getExpirationTime());
|
||||
|
||||
JWTClaimsSet remeberMeJwtClaims =new JWTClaimsSet.Builder()
|
||||
.issuer("")
|
||||
.subject(remeberMe.getUsername())
|
||||
.jwtID(remeberMe.getId())
|
||||
.issueTime(remeberMe.getLastLoginTime())
|
||||
.expirationTime(remeberMe.getExpirationTime())
|
||||
.claim("kid", HMAC512Service.MXK_AUTH_JWK)
|
||||
.build();
|
||||
|
||||
return authJwtService.signedJWT(remeberMeJwtClaims);
|
||||
}
|
||||
|
||||
public Integer getValidity() {
|
||||
return validity;
|
||||
}
|
||||
|
||||
public void setValidity(Integer validity) {
|
||||
this.validity = validity;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
package org.maxkey.authn.support.rememberme;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.maxkey.constants.ConstsTimeInterval;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Cache;
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
|
||||
public class InMemoryRemeberMeService extends AbstractRemeberMeService {
|
||||
|
||||
protected static final Cache<String, RemeberMe> remeberMeStore =
|
||||
Caffeine.newBuilder()
|
||||
.expireAfterWrite(ConstsTimeInterval.TWO_WEEK, TimeUnit.SECONDS)
|
||||
.build();
|
||||
|
||||
@Override
|
||||
public void save(RemeberMe remeberMe) {
|
||||
remeberMeStore.put(remeberMe.getUsername(), remeberMe);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(RemeberMe remeberMe) {
|
||||
remeberMeStore.put(remeberMe.getUsername(), remeberMe);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RemeberMe read(RemeberMe remeberMe) {
|
||||
return remeberMeStore.getIfPresent(remeberMe.getUsername());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(String username) {
|
||||
remeberMeStore.invalidate(username);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
package org.maxkey.authn.support.rememberme;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import java.util.List;
|
||||
|
||||
import org.maxkey.authn.jwt.AuthJwtService;
|
||||
import org.maxkey.configuration.ApplicationConfig;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
|
||||
public class JdbcRemeberMeService extends AbstractRemeberMeService {
|
||||
private static final Logger _logger = LoggerFactory.getLogger(JdbcRemeberMeService.class);
|
||||
|
||||
private static final String DEFAULT_DEFAULT_INSERT_STATEMENT =
|
||||
"insert into mxk_remember_me(id, userid,username,lastlogintime,expirationtime)values( ? , ? , ? , ? , ?)";
|
||||
|
||||
private static final String DEFAULT_DEFAULT_SELECT_STATEMENT =
|
||||
"select id, userid,username,lastlogintime,expirationtime from mxk_remember_me "
|
||||
+ " where id = ? and username = ?";
|
||||
|
||||
private static final String DEFAULT_DEFAULT_DELETE_STATEMENT =
|
||||
"delete from mxk_remember_me where username = ?";
|
||||
|
||||
private static final String DEFAULT_DEFAULT_UPDATE_STATEMENT =
|
||||
"update mxk_remember_me set lastlogintime = ? , expirationtime = ? where id = ?";
|
||||
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
|
||||
public JdbcRemeberMeService(
|
||||
JdbcTemplate jdbcTemplate,
|
||||
ApplicationConfig applicationConfig,
|
||||
AuthJwtService authJwtService) {
|
||||
this.jdbcTemplate = jdbcTemplate;
|
||||
this.applicationConfig = applicationConfig;
|
||||
this.authJwtService = authJwtService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(RemeberMe remeberMe) {
|
||||
jdbcTemplate.update(DEFAULT_DEFAULT_INSERT_STATEMENT,
|
||||
new Object[] {
|
||||
remeberMe.getId(),
|
||||
remeberMe.getUserId(),
|
||||
remeberMe.getUsername(),
|
||||
remeberMe.getLastLoginTime(),
|
||||
remeberMe.getExpirationTime()},
|
||||
new int[] {
|
||||
Types.VARCHAR,
|
||||
Types.VARCHAR,
|
||||
Types.VARCHAR,
|
||||
Types.TIMESTAMP,
|
||||
Types.TIMESTAMP
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(RemeberMe remeberMe) {
|
||||
jdbcTemplate.update(DEFAULT_DEFAULT_UPDATE_STATEMENT,
|
||||
new Object[] {
|
||||
remeberMe.getLastLoginTime(),
|
||||
remeberMe.getExpirationTime(),
|
||||
remeberMe.getId()
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public RemeberMe read(RemeberMe remeberMe) {
|
||||
List<RemeberMe> listRemeberMe = jdbcTemplate.query(DEFAULT_DEFAULT_SELECT_STATEMENT,
|
||||
new RowMapper<RemeberMe>() {
|
||||
public RemeberMe mapRow(ResultSet rs, int rowNum) throws SQLException {
|
||||
RemeberMe remeberMe = new RemeberMe();
|
||||
remeberMe.setId(rs.getString(1));
|
||||
remeberMe.setUserId(rs.getString(2));
|
||||
remeberMe.setUsername(rs.getString(3));
|
||||
remeberMe.setLastLoginTime(rs.getDate(4));
|
||||
return remeberMe;
|
||||
}
|
||||
}, remeberMe.getId(), remeberMe.getUsername());
|
||||
_logger.debug("listRemeberMe " + listRemeberMe);
|
||||
return (listRemeberMe.size() > 0) ? listRemeberMe.get(0) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(String username) {
|
||||
jdbcTemplate.update(DEFAULT_DEFAULT_DELETE_STATEMENT, username);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
package org.maxkey.authn.support.rememberme;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
public class RemeberMe implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 8010496585233991785L;
|
||||
|
||||
String id;
|
||||
|
||||
String userId;
|
||||
|
||||
String username;
|
||||
|
||||
Date lastLoginTime;
|
||||
|
||||
Date expirationTime;
|
||||
|
||||
public RemeberMe() {
|
||||
super();
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(String userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public Date getLastLoginTime() {
|
||||
return lastLoginTime;
|
||||
}
|
||||
|
||||
public void setLastLoginTime(Date lastLoginTime) {
|
||||
this.lastLoginTime = lastLoginTime;
|
||||
}
|
||||
|
||||
public Date getExpirationTime() {
|
||||
return expirationTime;
|
||||
}
|
||||
|
||||
public void setExpirationTime(Date expirationTime) {
|
||||
this.expirationTime = expirationTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("RemeberMe [id=");
|
||||
builder.append(id);
|
||||
builder.append(", userId=");
|
||||
builder.append(userId);
|
||||
builder.append(", username=");
|
||||
builder.append(username);
|
||||
builder.append(", lastLoginTime=");
|
||||
builder.append(lastLoginTime);
|
||||
builder.append(", expirationTime=");
|
||||
builder.append(expirationTime);
|
||||
builder.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright [2021] [MaxKey of copyright http://www.maxkey.top]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
package org.maxkey.authn.support.rememberme;
|
||||
|
||||
import org.maxkey.constants.ConstsPersistence;
|
||||
import org.maxkey.persistence.redis.RedisConnectionFactory;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
||||
public class RemeberMeServiceFactory {
|
||||
private static final Logger _logger =
|
||||
LoggerFactory.getLogger(RemeberMeServiceFactory.class);
|
||||
|
||||
public AbstractRemeberMeService getService(
|
||||
int persistence,
|
||||
JdbcTemplate jdbcTemplate,
|
||||
RedisConnectionFactory redisConnFactory){
|
||||
|
||||
AbstractRemeberMeService remeberMeService = null;
|
||||
if (persistence == ConstsPersistence.INMEMORY) {
|
||||
remeberMeService = new InMemoryRemeberMeService();
|
||||
_logger.debug("InMemoryRemeberMeService");
|
||||
} else if (persistence == ConstsPersistence.JDBC) {
|
||||
//remeberMeService = new JdbcRemeberMeService(jdbcTemplate);
|
||||
_logger.debug("JdbcRemeberMeService not support ");
|
||||
} else if (persistence == ConstsPersistence.REDIS) {
|
||||
_logger.debug("RedisRemeberMeService not support ");
|
||||
}
|
||||
return remeberMeService;
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,8 @@ import org.maxkey.authn.provider.TrustedAuthenticationProvider;
|
||||
import org.maxkey.authn.realm.AbstractAuthenticationRealm;
|
||||
import org.maxkey.authn.session.SessionManager;
|
||||
import org.maxkey.authn.session.SessionManagerFactory;
|
||||
import org.maxkey.authn.support.rememberme.AbstractRemeberMeService;
|
||||
import org.maxkey.authn.support.rememberme.JdbcRemeberMeService;
|
||||
import org.maxkey.authn.web.HttpSessionListenerAdapter;
|
||||
import org.maxkey.configuration.ApplicationConfig;
|
||||
import org.maxkey.configuration.AuthJwkConfig;
|
||||
@@ -181,7 +183,7 @@ public class AuthenticationAutoConfiguration implements InitializingBean {
|
||||
}
|
||||
|
||||
|
||||
@Bean(name = "sessionManager")
|
||||
@Bean
|
||||
public SessionManager sessionManager(
|
||||
@Value("${maxkey.server.persistence}") int persistence,
|
||||
JdbcTemplate jdbcTemplate,
|
||||
@@ -195,7 +197,22 @@ public class AuthenticationAutoConfiguration implements InitializingBean {
|
||||
return sessionManager;
|
||||
}
|
||||
|
||||
@Bean(name = "httpSessionListenerAdapter")
|
||||
|
||||
/**
|
||||
* remeberMeService .
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public AbstractRemeberMeService remeberMeService(
|
||||
@Value("${maxkey.server.persistence}") int persistence,
|
||||
@Value("${maxkey.login.remeberme.validity}") int validity,
|
||||
ApplicationConfig applicationConfig,
|
||||
AuthJwtService authJwtService,
|
||||
JdbcTemplate jdbcTemplate) {
|
||||
return new JdbcRemeberMeService(jdbcTemplate,applicationConfig,authJwtService);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public HttpSessionListenerAdapter httpSessionListenerAdapter() {
|
||||
return new HttpSessionListenerAdapter();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user