mirror of
https://gitee.com/dromara/MaxKey.git
synced 2026-05-14 20:50:14 +08:00
220413
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
|
||||
* 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
|
||||
* 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.
|
||||
@@ -156,42 +156,30 @@ public class RealmAuthenticationProvider extends AbstractAuthenticationProvider
|
||||
}
|
||||
|
||||
public UsernamePasswordAuthenticationToken createOnlineSession(LoginCredential credential,UserInfo userInfo) {
|
||||
String currentUserSessionId = WebContext.genId();
|
||||
//Online Tickit Id
|
||||
String onlineTickitId = WebConstants.ONLINE_TICKET_PREFIX + "-" + currentUserSessionId;
|
||||
_logger.debug("set online Tickit Cookie {} on domain {}",
|
||||
onlineTickitId,
|
||||
this.applicationConfig.getBaseDomainName()
|
||||
);
|
||||
//Online Tickit
|
||||
OnlineTicket onlineTicket = new OnlineTicket();
|
||||
|
||||
userInfo.setOnlineTicket(onlineTicket.getTicketId());
|
||||
|
||||
OnlineTicket onlineTicket = new OnlineTicket(onlineTickitId);
|
||||
|
||||
//set ONLINE_TICKET cookie
|
||||
WebContext.setCookie(WebContext.getResponse(),
|
||||
this.applicationConfig.getBaseDomainName(),
|
||||
WebConstants.ONLINE_TICKET_NAME,
|
||||
onlineTickitId);
|
||||
userInfo.setOnlineTicket(currentUserSessionId);
|
||||
|
||||
SigninPrincipal signinPrincipal = new SigninPrincipal(userInfo);
|
||||
SigninPrincipal principal = new SigninPrincipal(userInfo);
|
||||
//set OnlineTicket
|
||||
signinPrincipal.setOnlineTicket(onlineTicket);
|
||||
principal.setOnlineTicket(onlineTicket);
|
||||
ArrayList<GrantedAuthority> grantedAuthoritys = authenticationRealm.grantAuthority(userInfo);
|
||||
signinPrincipal.setAuthenticated(true);
|
||||
principal.setAuthenticated(true);
|
||||
|
||||
for(GrantedAuthority administratorsAuthority : grantedAdministratorsAuthoritys) {
|
||||
if(grantedAuthoritys.contains(administratorsAuthority)) {
|
||||
signinPrincipal.setRoleAdministrators(true);
|
||||
principal.setRoleAdministrators(true);
|
||||
_logger.trace("ROLE ADMINISTRATORS Authentication .");
|
||||
}
|
||||
}
|
||||
_logger.debug("Granted Authority {}" , grantedAuthoritys);
|
||||
|
||||
signinPrincipal.setGrantedAuthorityApps(authenticationRealm.queryAuthorizedApps(grantedAuthoritys));
|
||||
principal.setGrantedAuthorityApps(authenticationRealm.queryAuthorizedApps(grantedAuthoritys));
|
||||
|
||||
UsernamePasswordAuthenticationToken authenticationToken =
|
||||
new UsernamePasswordAuthenticationToken(
|
||||
signinPrincipal,
|
||||
principal,
|
||||
"PASSWORD",
|
||||
grantedAuthoritys
|
||||
);
|
||||
@@ -202,7 +190,7 @@ public class RealmAuthenticationProvider extends AbstractAuthenticationProvider
|
||||
onlineTicket.setAuthentication(authenticationToken);
|
||||
|
||||
//store onlineTicket
|
||||
this.onlineTicketServices.store(onlineTickitId, onlineTicket);
|
||||
this.onlineTicketServices.store(onlineTicket.getTicketId(), onlineTicket);
|
||||
|
||||
/*
|
||||
* put Authentication to current session context
|
||||
|
||||
@@ -1,3 +1,20 @@
|
||||
/*
|
||||
* 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.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
@@ -10,4 +27,4 @@ import java.lang.annotation.RetentionPolicy;
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface CurrentUser {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1,18 @@
|
||||
package org.maxkey.authn.annotation;
|
||||
/*
|
||||
* 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.annotation;
|
||||
|
||||
@@ -1,3 +1,20 @@
|
||||
/*
|
||||
* 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.jwt;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -35,18 +52,18 @@ public class AuthJwt {
|
||||
}
|
||||
|
||||
public AuthJwt(String token, Authentication authentication) {
|
||||
SigninPrincipal signinPrincipal = ((SigninPrincipal)authentication.getPrincipal());
|
||||
SigninPrincipal principal = ((SigninPrincipal)authentication.getPrincipal());
|
||||
|
||||
this.token = token;
|
||||
this.ticket = signinPrincipal.getOnlineTicket().getTicketId().substring(3);
|
||||
this.ticket = principal.getOnlineTicket().getTicketId();
|
||||
|
||||
this.id = signinPrincipal.getUserInfo().getId();
|
||||
this.username = signinPrincipal.getUserInfo().getUsername();
|
||||
this.id = principal.getUserInfo().getId();
|
||||
this.username = principal.getUserInfo().getUsername();
|
||||
this.name = this.username;
|
||||
this.displayName = signinPrincipal.getUserInfo().getDisplayName();
|
||||
this.email = signinPrincipal.getUserInfo().getEmail();
|
||||
this.instId = signinPrincipal.getUserInfo().getInstId();
|
||||
this.instName = signinPrincipal.getUserInfo().getInstName();
|
||||
this.displayName = principal.getUserInfo().getDisplayName();
|
||||
this.email = principal.getUserInfo().getEmail();
|
||||
this.instId = principal.getUserInfo().getInstId();
|
||||
this.instName = principal.getUserInfo().getInstName();
|
||||
|
||||
this.authorities = new ArrayList<String>();
|
||||
for(GrantedAuthority grantedAuthority :authentication.getAuthorities()) {
|
||||
|
||||
@@ -1,3 +1,20 @@
|
||||
/*
|
||||
* 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.jwt;
|
||||
|
||||
import java.text.ParseException;
|
||||
@@ -33,18 +50,18 @@ public class AuthJwtService {
|
||||
|
||||
public String generateToken(Authentication authentication) {
|
||||
String token = "";
|
||||
SigninPrincipal signinPrincipal = ((SigninPrincipal)authentication.getPrincipal());
|
||||
UserInfo userInfo = signinPrincipal.getUserInfo();
|
||||
SigninPrincipal principal = ((SigninPrincipal)authentication.getPrincipal());
|
||||
UserInfo userInfo = principal.getUserInfo();
|
||||
DateTime currentDateTime = DateTime.now();
|
||||
Date expirationTime = currentDateTime.plusSeconds(authJwkConfig.getExpires()).toDate();
|
||||
_logger.debug("expiration Time : {}" , expirationTime);
|
||||
String subject = signinPrincipal.getUsername();
|
||||
String subject = principal.getUsername();
|
||||
_logger.trace("jwt subject : {}" , subject);
|
||||
|
||||
JWTClaimsSet jwtClaims =new JWTClaimsSet.Builder()
|
||||
.issuer(authJwkConfig.getIssuer())
|
||||
.subject(subject)
|
||||
.jwtID(signinPrincipal.getOnlineTicket().getTicketId())
|
||||
.jwtID(principal.getOnlineTicket().getFormattedTicketId())
|
||||
.issueTime(currentDateTime.toDate())
|
||||
.expirationTime(expirationTime)
|
||||
.claim("locale", userInfo.getLocale())
|
||||
|
||||
@@ -1 +1,18 @@
|
||||
package org.maxkey.authn.jwt;
|
||||
/*
|
||||
* 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.jwt;
|
||||
|
||||
@@ -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.online;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import java.time.LocalTime;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.maxkey.entity.HistoryLogin;
|
||||
import org.maxkey.entity.UserInfo;
|
||||
import org.maxkey.util.DateUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
|
||||
public class AbstractOnlineTicketService implements OnlineTicketService{
|
||||
private static Logger _logger = LoggerFactory.getLogger(AbstractOnlineTicketService.class);
|
||||
|
||||
protected JdbcTemplate jdbcTemplate;
|
||||
|
||||
private static final String DEFAULT_DEFAULT_SELECT_STATEMENT =
|
||||
"select id,sessionid,userId,username,displayname,logintime from mxk_history_login where sessionstatus = 1";
|
||||
|
||||
private static final String LOGOUT_USERINFO_UPDATE_STATEMENT =
|
||||
"update mxk_userinfo set lastlogofftime = ? , online = " + UserInfo.ONLINE.OFFLINE + " where id = ?";
|
||||
|
||||
private static final String HISTORY_LOGOUT_UPDATE_STATEMENT =
|
||||
"update mxk_history_login set logouttime = ? ,sessionstatus = 7 where sessionid = ?";
|
||||
|
||||
|
||||
public List<HistoryLogin> query() {
|
||||
List<HistoryLogin> listOnlineTicket = jdbcTemplate.query(
|
||||
DEFAULT_DEFAULT_SELECT_STATEMENT,
|
||||
new OnlineTicketRowMapper());
|
||||
return listOnlineTicket;
|
||||
}
|
||||
|
||||
public void profileLastLogoffTime(String userId,String lastLogoffTime) {
|
||||
_logger.trace("userId {} , lastlogofftime {}" ,userId, lastLogoffTime);
|
||||
jdbcTemplate.update( LOGOUT_USERINFO_UPDATE_STATEMENT,
|
||||
new Object[] { lastLogoffTime, userId },
|
||||
new int[] { Types.TIMESTAMP, Types.VARCHAR });
|
||||
}
|
||||
|
||||
public void sessionLogoff(String sessionId,String lastLogoffTime) {
|
||||
_logger.trace("sessionId {} , lastlogofftime {}" ,sessionId, lastLogoffTime);
|
||||
jdbcTemplate.update(HISTORY_LOGOUT_UPDATE_STATEMENT,
|
||||
new Object[] { lastLogoffTime, sessionId },
|
||||
new int[] { Types.VARCHAR, Types.VARCHAR });
|
||||
}
|
||||
|
||||
@Override
|
||||
public void terminate(String onlineTicket,String userId,String username) {
|
||||
String lastLogoffTime = DateUtils.formatDateTime(new Date());
|
||||
_logger.trace("{} user {} terminate Ticket {} ." ,lastLogoffTime,username, onlineTicket);
|
||||
this.profileLastLogoffTime(userId, lastLogoffTime);
|
||||
this.sessionLogoff(userId, lastLogoffTime);
|
||||
remove(onlineTicket);
|
||||
}
|
||||
|
||||
private final class OnlineTicketRowMapper implements RowMapper<HistoryLogin> {
|
||||
@Override
|
||||
public HistoryLogin mapRow(ResultSet rs, int rowNum)
|
||||
throws SQLException {
|
||||
HistoryLogin history=new HistoryLogin();
|
||||
history.setId(rs.getString(1));
|
||||
history.setSessionId(rs.getString(2));
|
||||
history.setUserId(rs.getString(3));
|
||||
history.setUsername(rs.getString(4));
|
||||
history.setDisplayName(rs.getString(5));
|
||||
history.setLoginTime(rs.getString(6));
|
||||
return history;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void store(String ticketId, OnlineTicket ticket) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public OnlineTicket remove(String ticket) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OnlineTicket get(String ticketId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh(String ticketId, LocalTime refreshTime) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh(String ticketId) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValiditySeconds(int validitySeconds) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -23,12 +23,13 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Cache;
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
|
||||
|
||||
public class InMemoryOnlineTicketService implements OnlineTicketService{
|
||||
public class InMemoryOnlineTicketService extends AbstractOnlineTicketService{
|
||||
private static final Logger _logger = LoggerFactory.getLogger(InMemoryOnlineTicketService.class);
|
||||
|
||||
protected static Cache<String, OnlineTicket> onlineTicketStore =
|
||||
@@ -37,8 +38,9 @@ public class InMemoryOnlineTicketService implements OnlineTicketService{
|
||||
.maximumSize(200000)
|
||||
.build();
|
||||
|
||||
public InMemoryOnlineTicketService() {
|
||||
public InMemoryOnlineTicketService(JdbcTemplate jdbcTemplate) {
|
||||
super();
|
||||
this.jdbcTemplate = jdbcTemplate;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -22,18 +22,16 @@ import java.time.LocalTime;
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.maxkey.entity.apps.Apps;
|
||||
import org.maxkey.web.WebContext;
|
||||
import org.springframework.security.core.Authentication;
|
||||
|
||||
public class OnlineTicket implements Serializable{
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 9008067569150338296L;
|
||||
|
||||
public static final String ONLINE_TICKET_PREFIX = "OT";
|
||||
|
||||
public static final int MAX_EXPIRY_DURATION = 60 * 10; //default 10 minutes.
|
||||
|
||||
private static final long serialVersionUID = 9008067569150338296L;
|
||||
|
||||
public String ticketId;
|
||||
|
||||
public LocalTime ticketTime;
|
||||
@@ -42,6 +40,11 @@ public class OnlineTicket implements Serializable{
|
||||
|
||||
private HashMap<String , Apps> authorizedApps = new HashMap<String , Apps>();
|
||||
|
||||
public OnlineTicket() {
|
||||
super();
|
||||
this.ticketId = WebContext.genId();;
|
||||
this.ticketTime = LocalTime.now();
|
||||
}
|
||||
|
||||
public OnlineTicket(String ticketId) {
|
||||
super();
|
||||
@@ -56,18 +59,17 @@ public class OnlineTicket implements Serializable{
|
||||
this.ticketTime = LocalTime.now();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public String getTicketId() {
|
||||
return ticketId;
|
||||
}
|
||||
|
||||
public String getFormattedTicketId() {
|
||||
return ticketId;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void setTicketId(String ticketId) {
|
||||
this.ticketId = ticketId;
|
||||
}
|
||||
|
||||
|
||||
public LocalTime getTicketTime() {
|
||||
return ticketTime;
|
||||
@@ -81,20 +83,14 @@ public class OnlineTicket implements Serializable{
|
||||
return authentication;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void setAuthentication(Authentication authentication) {
|
||||
this.authentication = authentication;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public HashMap<String, Apps> getAuthorizedApps() {
|
||||
return authorizedApps;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void setAuthorizedApps(HashMap<String, Apps> authorizedApps) {
|
||||
this.authorizedApps = authorizedApps;
|
||||
}
|
||||
@@ -103,8 +99,6 @@ public class OnlineTicket implements Serializable{
|
||||
this.authorizedApps.put(authorizedApp.getId(), authorizedApp);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
|
||||
* 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.
|
||||
@@ -32,4 +32,6 @@ public interface OnlineTicketService {
|
||||
public void refresh(String ticketId);
|
||||
|
||||
public void setValiditySeconds(int validitySeconds);
|
||||
|
||||
public void terminate(String onlineTicket,String userId,String username);
|
||||
}
|
||||
|
||||
@@ -34,12 +34,12 @@ public class OnlineTicketServiceFactory {
|
||||
|
||||
OnlineTicketService onlineTicketServices = null;
|
||||
if (persistence == ConstsPersistence.INMEMORY) {
|
||||
onlineTicketServices = new InMemoryOnlineTicketService();
|
||||
onlineTicketServices = new InMemoryOnlineTicketService(jdbcTemplate);
|
||||
_logger.debug("InMemoryOnlineTicketServices");
|
||||
} else if (persistence == ConstsPersistence.JDBC) {
|
||||
_logger.debug("OnlineTicketServices not support ");
|
||||
} else if (persistence == ConstsPersistence.REDIS) {
|
||||
onlineTicketServices = new RedisOnlineTicketService(redisConnFactory);
|
||||
onlineTicketServices = new RedisOnlineTicketService(redisConnFactory,jdbcTemplate);
|
||||
_logger.debug("RedisOnlineTicketServices");
|
||||
}
|
||||
|
||||
|
||||
@@ -24,9 +24,10 @@ import org.maxkey.persistence.redis.RedisConnection;
|
||||
import org.maxkey.persistence.redis.RedisConnectionFactory;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
||||
|
||||
public class RedisOnlineTicketService implements OnlineTicketService {
|
||||
public class RedisOnlineTicketService extends AbstractOnlineTicketService {
|
||||
private static final Logger _logger = LoggerFactory.getLogger(RedisOnlineTicketService.class);
|
||||
|
||||
protected int serviceTicketValiditySeconds = 60 * 30; //default 30 minutes.
|
||||
@@ -37,9 +38,12 @@ public class RedisOnlineTicketService implements OnlineTicketService {
|
||||
/**
|
||||
* @param connectionFactory
|
||||
*/
|
||||
public RedisOnlineTicketService(RedisConnectionFactory connectionFactory) {
|
||||
public RedisOnlineTicketService(
|
||||
RedisConnectionFactory connectionFactory,
|
||||
JdbcTemplate jdbcTemplate) {
|
||||
super();
|
||||
this.connectionFactory = connectionFactory;
|
||||
this.jdbcTemplate = jdbcTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -20,7 +20,6 @@ package org.maxkey.authn.realm;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.maxkey.authn.SigninPrincipal;
|
||||
import org.maxkey.authn.realm.ldap.LdapAuthenticationRealmService;
|
||||
@@ -157,32 +156,6 @@ public abstract class AbstractAuthenticationRealm {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* logout user and remove RemeberMe token
|
||||
* @param response
|
||||
* @return
|
||||
*/
|
||||
public boolean logout(HttpServletResponse response) {
|
||||
Authentication authentication = (Authentication ) WebContext.getAttribute(WebConstants.AUTHENTICATION);
|
||||
|
||||
if(authentication != null && authentication.getPrincipal() instanceof SigninPrincipal) {
|
||||
SigninPrincipal signinPrincipal = ((SigninPrincipal) authentication.getPrincipal());
|
||||
UserInfo userInfo = signinPrincipal.getUserInfo();
|
||||
userInfo.setLastLogoffTime(DateUtils.formatDateTime(new Date()));
|
||||
|
||||
loginHistoryRepository.logoff(userInfo.getLastLogoffTime(), signinPrincipal.getOnlineTicket().getTicketId());
|
||||
|
||||
|
||||
loginRepository.updateLastLogoff(userInfo);
|
||||
|
||||
_logger.debug("Session " + signinPrincipal.getOnlineTicket().getTicketId() + ", user "
|
||||
+ userInfo.getUsername() + " Logout, datetime " + userInfo.getLastLogoffTime() + " .");
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public Browser resolveBrowser() {
|
||||
Browser browser =new Browser();
|
||||
|
||||
@@ -1,3 +1,20 @@
|
||||
/*
|
||||
* 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.web;
|
||||
|
||||
import java.text.ParseException;
|
||||
@@ -17,7 +34,7 @@ import org.springframework.security.core.Authentication;
|
||||
|
||||
public class AuthorizationUtils {
|
||||
|
||||
static final String Authorization = "Authorization";
|
||||
static final String Authorization_Cookie = "AuthJWT";
|
||||
|
||||
public static void authenticateWithCookie(
|
||||
HttpServletRequest request,
|
||||
@@ -25,10 +42,10 @@ public class AuthorizationUtils {
|
||||
OnlineTicketService onlineTicketService
|
||||
) throws ParseException{
|
||||
if(getAuthentication() == null) {
|
||||
Cookie authCookie = WebContext.getCookie(request, Authorization);
|
||||
Cookie authCookie = WebContext.getCookie(request, Authorization_Cookie);
|
||||
if(authCookie != null ) {
|
||||
String authorization = authCookie.getValue();
|
||||
doAuthenticate(authorization,authJwtService,onlineTicketService);
|
||||
doJwtAuthenticate(authorization,authJwtService,onlineTicketService);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -41,12 +58,12 @@ public class AuthorizationUtils {
|
||||
if(getAuthentication() == null) {
|
||||
String authorization = AuthorizationHeaderUtils.resolveBearer(request);
|
||||
if(authorization != null ) {
|
||||
doAuthenticate(authorization,authJwtService,onlineTicketService);
|
||||
doJwtAuthenticate(authorization,authJwtService,onlineTicketService);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void doAuthenticate(
|
||||
public static void doJwtAuthenticate(
|
||||
String authorization,
|
||||
AuthJwtService authJwtService,
|
||||
OnlineTicketService onlineTicketService) throws ParseException {
|
||||
@@ -59,13 +76,17 @@ public class AuthorizationUtils {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void setAuthentication(Authentication authentication) {
|
||||
WebContext.setAttribute(WebConstants.AUTHENTICATION, authentication);
|
||||
}
|
||||
|
||||
public static Authentication getAuthentication() {
|
||||
Authentication authentication = (Authentication) WebContext.getAttribute(WebConstants.AUTHENTICATION);
|
||||
Authentication authentication = (Authentication) getAuthentication(WebContext.getRequest());
|
||||
return authentication;
|
||||
}
|
||||
|
||||
public static Authentication getAuthentication(HttpServletRequest request) {
|
||||
Authentication authentication = (Authentication) request.getSession().getAttribute(WebConstants.AUTHENTICATION);
|
||||
return authentication;
|
||||
}
|
||||
|
||||
@@ -74,22 +95,29 @@ public class AuthorizationUtils {
|
||||
}
|
||||
|
||||
public static boolean isNotAuthenticated() {
|
||||
return getAuthentication() == null;
|
||||
return ! isAuthenticated();
|
||||
}
|
||||
|
||||
public static SigninPrincipal getPrincipal() {
|
||||
Authentication authentication = getAuthentication();
|
||||
return authentication == null ? null :(SigninPrincipal) authentication.getPrincipal();
|
||||
return getPrincipal(authentication);
|
||||
}
|
||||
|
||||
public static UserInfo getUserInfo() {
|
||||
Authentication authentication = getAuthentication();
|
||||
public static SigninPrincipal getPrincipal(Authentication authentication) {
|
||||
return authentication == null ? null : (SigninPrincipal) authentication.getPrincipal();
|
||||
}
|
||||
|
||||
public static UserInfo getUserInfo(Authentication authentication) {
|
||||
UserInfo userInfo = null;
|
||||
if(isAuthenticated() && (authentication.getPrincipal() instanceof SigninPrincipal)) {
|
||||
SigninPrincipal signinPrincipal = ((SigninPrincipal) authentication.getPrincipal());
|
||||
userInfo = signinPrincipal.getUserInfo();
|
||||
SigninPrincipal principal = getPrincipal(authentication);
|
||||
if(principal != null ) {
|
||||
userInfo = principal.getUserInfo();
|
||||
}
|
||||
return userInfo;
|
||||
}
|
||||
|
||||
public static UserInfo getUserInfo() {
|
||||
return getUserInfo(getAuthentication());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,22 @@
|
||||
/*
|
||||
* 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.web;
|
||||
|
||||
import org.maxkey.authn.SigninPrincipal;
|
||||
import org.maxkey.authn.annotation.CurrentUser;
|
||||
import org.maxkey.entity.UserInfo;
|
||||
import org.maxkey.web.WebConstants;
|
||||
@@ -14,23 +30,23 @@ import org.springframework.web.method.support.ModelAndViewContainer;
|
||||
import org.springframework.web.multipart.support.MissingServletRequestPartException;
|
||||
|
||||
public class CurrentUserMethodArgumentResolver implements HandlerMethodArgumentResolver {
|
||||
|
||||
@Override
|
||||
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
|
||||
Authentication authentication =
|
||||
(Authentication ) webRequest.getAttribute(
|
||||
WebConstants.AUTHENTICATION, RequestAttributes.SCOPE_SESSION);
|
||||
UserInfo userInfo = AuthorizationUtils.getUserInfo(authentication);
|
||||
if (userInfo != null) {
|
||||
return userInfo;
|
||||
}
|
||||
throw new MissingServletRequestPartException("currentUser");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsParameter(MethodParameter parameter) {
|
||||
return parameter.getParameterType().isAssignableFrom(UserInfo.class)
|
||||
&& parameter.hasParameterAnnotation(CurrentUser.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
|
||||
UserInfo userInfo = null;
|
||||
Authentication authentication = (Authentication ) webRequest.getAttribute(WebConstants.AUTHENTICATION, RequestAttributes.SCOPE_SESSION);
|
||||
if((authentication != null) && (authentication.getPrincipal() instanceof SigninPrincipal)) {
|
||||
SigninPrincipal signinPrincipal = ((SigninPrincipal) authentication.getPrincipal());
|
||||
userInfo = signinPrincipal.getUserInfo();
|
||||
if (userInfo != null) {
|
||||
return userInfo;
|
||||
}
|
||||
}
|
||||
throw new MissingServletRequestPartException("currentUser");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright [2021] [MaxKey of copyright http://www.maxkey.top]
|
||||
* 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.
|
||||
@@ -22,48 +22,22 @@ import javax.servlet.http.HttpSession;
|
||||
import javax.servlet.http.HttpSessionEvent;
|
||||
import javax.servlet.http.HttpSessionListener;
|
||||
|
||||
import org.apache.mybatis.jpa.util.WebContext;
|
||||
import org.maxkey.authn.SigninPrincipal;
|
||||
import org.maxkey.entity.UserInfo;
|
||||
import org.maxkey.persistence.repository.LoginHistoryRepository;
|
||||
import org.maxkey.persistence.repository.LoginRepository;
|
||||
import org.maxkey.util.DateUtils;
|
||||
import org.maxkey.web.WebConstants;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
|
||||
@WebListener
|
||||
public class SessionListenerAdapter implements HttpSessionListener {
|
||||
|
||||
private static final Logger _logger = LoggerFactory.getLogger(SessionListenerAdapter.class);
|
||||
|
||||
LoginRepository loginRepository;
|
||||
|
||||
LoginHistoryRepository loginHistoryRepository;
|
||||
|
||||
public SessionListenerAdapter() {
|
||||
super();
|
||||
_logger.debug("SessionListenerAdapter inited . ");
|
||||
}
|
||||
|
||||
public SessionListenerAdapter(LoginRepository loginRepository, LoginHistoryRepository loginHistoryRepository) {
|
||||
super();
|
||||
this.loginRepository = loginRepository;
|
||||
this.loginHistoryRepository = loginHistoryRepository;
|
||||
_logger.debug("SessionListenerAdapter inited . ");
|
||||
}
|
||||
|
||||
public void init() {
|
||||
if(loginRepository == null ) {
|
||||
loginRepository = (LoginRepository)WebContext.getBean("loginRepository");
|
||||
loginHistoryRepository = (LoginHistoryRepository)WebContext.getBean("loginHistoryRepository");
|
||||
_logger.debug("SessionListenerAdapter function inited . ");
|
||||
}
|
||||
_logger.info("SecurityContextHolder StrategyName " + SessionSecurityContextHolderStrategy.class.getCanonicalName());
|
||||
SecurityContextHolder.setStrategyName(SessionSecurityContextHolderStrategy.class.getCanonicalName());
|
||||
}
|
||||
/**
|
||||
* session Created
|
||||
*/
|
||||
@@ -79,31 +53,16 @@ public class SessionListenerAdapter implements HttpSessionListener {
|
||||
public void sessionDestroyed(HttpSessionEvent sessionEvent) {
|
||||
HttpSession session = sessionEvent.getSession();
|
||||
Authentication authentication = (Authentication ) session.getAttribute(WebConstants.AUTHENTICATION);
|
||||
if(authentication != null && authentication.getPrincipal() instanceof SigninPrincipal) {
|
||||
SigninPrincipal signinPrincipal = ((SigninPrincipal) authentication.getPrincipal());
|
||||
_logger.trace("session Id : " + session.getId());
|
||||
init();
|
||||
UserInfo userInfo = signinPrincipal.getUserInfo();
|
||||
userInfo.setLastLogoffTime(DateUtils.formatDateTime(new Date()));
|
||||
loginRepository.updateLastLogoff(userInfo);
|
||||
loginHistoryRepository.logoff(userInfo.getLastLogoffTime(), userInfo.getOnlineTicket());
|
||||
|
||||
_logger.debug(
|
||||
"session {} Destroyed as {} userId : {} , username : {}" ,
|
||||
userInfo.getOnlineTicket(),
|
||||
userInfo.getLastLogoffTime(),
|
||||
userInfo.getId(),
|
||||
userInfo.getUsername());
|
||||
SigninPrincipal principal = AuthorizationUtils.getPrincipal(authentication);
|
||||
if(principal != null ) {
|
||||
_logger.trace("{} HttpSession Id {} for userId {} , username {} @Ticket {} Destroyed" ,
|
||||
DateUtils.formatDateTime(new Date()),
|
||||
session.getId(),
|
||||
principal.getUserInfo().getId(),
|
||||
principal.getUserInfo().getUsername(),
|
||||
principal.getOnlineTicket().getTicketId());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void setLoginRepository(LoginRepository loginRepository) {
|
||||
this.loginRepository = loginRepository;
|
||||
}
|
||||
|
||||
public void setLoginHistoryRepository(LoginHistoryRepository loginHistoryRepository) {
|
||||
this.loginHistoryRepository = loginHistoryRepository;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,3 +1,20 @@
|
||||
/*
|
||||
* 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.web;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
|
||||
* 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.
|
||||
@@ -33,8 +33,6 @@ import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.servlet.AsyncHandlerInterceptor;
|
||||
/**
|
||||
* 权限Interceptor处理
|
||||
* 权限处理需在servlet.xml中配置
|
||||
* mvc:interceptors permission
|
||||
* @author Crystal.Sea
|
||||
*
|
||||
*/
|
||||
@@ -51,6 +49,8 @@ public class PermissionInterceptor implements AsyncHandlerInterceptor {
|
||||
@Autowired
|
||||
AuthJwtService authJwtService ;
|
||||
|
||||
boolean mgmt = false;
|
||||
|
||||
/*
|
||||
* 请求前处理
|
||||
* (non-Javadoc)
|
||||
@@ -60,25 +60,29 @@ public class PermissionInterceptor implements AsyncHandlerInterceptor {
|
||||
public boolean preHandle(HttpServletRequest request,HttpServletResponse response, Object handler) throws Exception {
|
||||
_logger.trace("PermissionAdapter preHandle");
|
||||
AuthorizationUtils.authenticate(request, authJwtService, onlineTicketService);
|
||||
//判断用户是否登录
|
||||
if(AuthorizationUtils.getAuthentication()==null
|
||||
||AuthorizationUtils.getAuthentication().getAuthorities()==null){//判断用户和角色,判断用户是否登录用户
|
||||
SigninPrincipal principal = AuthorizationUtils.getPrincipal();
|
||||
//判断用户是否登录,判断用户是否登录用户
|
||||
if(principal == null){
|
||||
_logger.trace("No Authentication ... forward to /auth/entrypoint");
|
||||
RequestDispatcher dispatcher = request.getRequestDispatcher("/auth/entrypoint");
|
||||
dispatcher.forward(request, response);
|
||||
return false;
|
||||
}
|
||||
|
||||
//非管理员用户直接注销
|
||||
if (!((SigninPrincipal) AuthorizationUtils.getAuthentication().getPrincipal()).isRoleAdministrators()) {
|
||||
//管理端必须使用管理员登录,非管理员用户直接注销
|
||||
if (this.mgmt && !principal.isRoleAdministrators()) {
|
||||
_logger.debug("Not ADMINISTRATORS Authentication .");
|
||||
RequestDispatcher dispatcher = request.getRequestDispatcher("/logout");
|
||||
RequestDispatcher dispatcher = request.getRequestDispatcher("/auth/entrypoint");
|
||||
dispatcher.forward(request, response);
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean hasAccess=true;
|
||||
|
||||
return hasAccess;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setMgmt(boolean mgmt) {
|
||||
this.mgmt = mgmt;
|
||||
_logger.debug("Permission for ADMINISTRATORS {}", this.mgmt);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1 +1,18 @@
|
||||
package org.maxkey.authn.web.interceptor;
|
||||
/*
|
||||
* 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.web.interceptor;
|
||||
|
||||
@@ -1 +1,18 @@
|
||||
package org.maxkey.authn.web;
|
||||
/*
|
||||
* 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.web;
|
||||
|
||||
@@ -137,13 +137,8 @@ public class AuthenticationAutoConfiguration implements InitializingBean {
|
||||
}
|
||||
|
||||
@Bean(name = "sessionListenerAdapter")
|
||||
public SessionListenerAdapter sessionListenerAdapter(
|
||||
LoginRepository loginRepository,
|
||||
LoginHistoryRepository loginHistoryRepository
|
||||
) {
|
||||
SessionListenerAdapter sessionListenerAdapter =
|
||||
new SessionListenerAdapter(loginRepository,loginHistoryRepository);
|
||||
return sessionListenerAdapter;
|
||||
public SessionListenerAdapter sessionListenerAdapter() {
|
||||
return new SessionListenerAdapter();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user