diff --git a/ReleaseNotes.txt b/ReleaseNotes.txt index 765b0c272..78f25371d 100644 --- a/ReleaseNotes.txt +++ b/ReleaseNotes.txt @@ -1,6 +1,6 @@ -MaxKey v 2.3.0 GA 2020/**/** +MaxKey v 2.3.0 GA 2020/11/** *(MAXKEY-200901) 基于spring session的集群会话共享功能 - *(MAXKEY-200902) 单点注销功能 + *(MAXKEY-200902) 单点注销功能,应用可以配置为NONE/BACK_CHANNEL/FRONT_CHANNEL三种方式,支持CAS/SAML/Default *(MAXKEY-200903) 用户在线实时更新功能 *(MAXKEY-200904) 批量Excel用户导入功能 *(MAXKEY-200905) 用户注册功能 @@ -13,6 +13,9 @@ *(MAXKEY-200913) 权限控制 RoleAdministrators *(MAXKEY-200914) 社交账号登录优化 *(MAXKEY-200915) 列表界面中未”选择“情况下,弹出界面错误 + *(MAXKEY-200916) jib(docker) 支持 ,感谢https://github.com/alanland + *(MAXKEY-200916) 登录过程的优化 + *(MAXKEY-200917) 认证的优化,支持@Principal的注入 *(MAXKEY-200920) 依赖jar引用、更新和升级 druid 1.2.1 JustAuth 1.15.8 diff --git a/maxkey-core/src/main/java/org/maxkey/authn/RealmAuthenticationProvider.java b/maxkey-core/src/main/java/org/maxkey/authn/RealmAuthenticationProvider.java index 25a4d4e3f..dd8a476fa 100644 --- a/maxkey-core/src/main/java/org/maxkey/authn/RealmAuthenticationProvider.java +++ b/maxkey-core/src/main/java/org/maxkey/authn/RealmAuthenticationProvider.java @@ -29,7 +29,6 @@ import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.web.authentication.WebAuthenticationDetails; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; @@ -162,10 +161,6 @@ public class RealmAuthenticationProvider extends AbstractAuthenticationProvider //set OnlineTicket signinPrincipal.setOnlineTicket(onlineTicket); ArrayList grantedAuthoritys = authenticationRealm.grantAuthority(userInfo); - //set default roles - grantedAuthoritys.add(new SimpleGrantedAuthority("ROLE_USER")); - grantedAuthoritys.add(new SimpleGrantedAuthority("ROLE_ORDINARY_USER")); - signinPrincipal.setAuthenticated(true); for(GrantedAuthority administratorsAuthority : grantedAdministratorsAuthoritys) { @@ -174,6 +169,9 @@ public class RealmAuthenticationProvider extends AbstractAuthenticationProvider _logger.trace("ROLE ADMINISTRATORS Authentication ."); } } + _logger.debug("Granted Authority " + grantedAuthoritys); + + signinPrincipal.setGrantedAuthorityApps(authenticationRealm.queryAuthorizedApps(grantedAuthoritys)); UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken( diff --git a/maxkey-core/src/main/java/org/maxkey/authn/SigninPrincipal.java b/maxkey-core/src/main/java/org/maxkey/authn/SigninPrincipal.java index ee6a83970..ff1e20d2d 100644 --- a/maxkey-core/src/main/java/org/maxkey/authn/SigninPrincipal.java +++ b/maxkey-core/src/main/java/org/maxkey/authn/SigninPrincipal.java @@ -34,6 +34,7 @@ public class SigninPrincipal implements UserDetails { OnlineTicket onlineTicket; ArrayList grantedAuthority; + ArrayList grantedAuthorityApps; boolean authenticated; boolean roleAdministrators; @@ -133,6 +134,14 @@ public class SigninPrincipal implements UserDetails { return false; } + public ArrayList getGrantedAuthorityApps() { + return grantedAuthorityApps; + } + + public void setGrantedAuthorityApps(ArrayList grantedAuthorityApps) { + this.grantedAuthorityApps = grantedAuthorityApps; + } + @Override public String getUsername() { if(this.userInfo != null) { diff --git a/maxkey-core/src/main/java/org/maxkey/authn/realm/AbstractAuthenticationRealm.java b/maxkey-core/src/main/java/org/maxkey/authn/realm/AbstractAuthenticationRealm.java index 7a2b808f1..7237b6341 100644 --- a/maxkey-core/src/main/java/org/maxkey/authn/realm/AbstractAuthenticationRealm.java +++ b/maxkey-core/src/main/java/org/maxkey/authn/realm/AbstractAuthenticationRealm.java @@ -110,6 +110,16 @@ public abstract class AbstractAuthenticationRealm { public ArrayList grantAuthority(UserInfo userInfo) { return loginService.grantAuthority(userInfo); } + + /** + * grant Authority by grantedAuthoritys + * + * @param grantedAuthoritys + * @return ArrayList + */ + public ArrayList queryAuthorizedApps(ArrayList grantedAuthoritys) { + return loginService.queryAuthorizedApps(grantedAuthoritys); + } /** * login log write to log db diff --git a/maxkey-core/src/main/java/org/maxkey/persistence/db/LoginService.java b/maxkey-core/src/main/java/org/maxkey/persistence/db/LoginService.java index 2ae578a24..96524c9a6 100644 --- a/maxkey-core/src/main/java/org/maxkey/persistence/db/LoginService.java +++ b/maxkey-core/src/main/java/org/maxkey/persistence/db/LoginService.java @@ -56,6 +56,8 @@ public class LoginService { private static final String DEFAULT_USERINFO_SELECT_STATEMENT = "SELECT * FROM MXK_USERINFO WHERE USERNAME = ?"; + private static final String DEFAULT_MYAPPS_SELECT_STATEMENT = "SELECT DISTINCT APP.ID,APP.NAME FROM MXK_APPS APP,MXK_GROUP_PRIVILEGES GP,MXK_GROUPS G WHERE APP.ID=GP.APPID AND GP.GROUPID=G.ID AND G.ID IN(%s)"; + protected JdbcTemplate jdbcTemplate; public LoginService(){ @@ -151,6 +153,24 @@ public class LoginService { } } + public ArrayList queryAuthorizedApps(ArrayList grantedAuthoritys) { + String grantedAuthorityString="'ROLE_ALL_USER'"; + for(GrantedAuthority grantedAuthority : grantedAuthoritys) { + grantedAuthorityString += ",'"+ grantedAuthority.getAuthority()+"'"; + } + + ArrayList listAuthorizedApps = (ArrayList) jdbcTemplate.query( + String.format(DEFAULT_MYAPPS_SELECT_STATEMENT, grantedAuthorityString), + new RowMapper() { + public GrantedAuthority mapRow(ResultSet rs, int rowNum) throws SQLException { + return new SimpleGrantedAuthority(rs.getString("ID")); + } + }); + + _logger.debug("list Authorized Apps " + listAuthorizedApps); + return listAuthorizedApps; + } + public List queryGroups(UserInfo userInfo) { List listGroups = jdbcTemplate.query(GROUPS_SELECT_STATEMENT, new RowMapper() { public Groups mapRow(ResultSet rs, int rowNum) throws SQLException { @@ -174,9 +194,11 @@ public class LoginService { // query roles for user List listGroups = queryGroups(userInfo); - // set role for spring security + //set default roles ArrayList grantedAuthority = new ArrayList(); grantedAuthority.add(new SimpleGrantedAuthority("ROLE_USER")); + grantedAuthority.add(new SimpleGrantedAuthority("ROLE_ORDINARY_USER")); + grantedAuthority.add(new SimpleGrantedAuthority("ROLE_ALL_USER")); for (Groups group : listGroups) { grantedAuthority.add(new SimpleGrantedAuthority(group.getId())); } diff --git a/maxkey-persistence/src/main/resources/org/maxkey/persistence/mapper/xml/mysql/AppsMapper.xml b/maxkey-persistence/src/main/resources/org/maxkey/persistence/mapper/xml/mysql/AppsMapper.xml index e5c2d680e..d4d49d4c4 100644 --- a/maxkey-persistence/src/main/resources/org/maxkey/persistence/mapper/xml/mysql/AppsMapper.xml +++ b/maxkey-persistence/src/main/resources/org/maxkey/persistence/mapper/xml/mysql/AppsMapper.xml @@ -158,29 +158,24 @@ SELECT DISTINCT APP.* FROM - MXK_APPS APP,MXK_GROUP_PRIVILEGES GP + MXK_APPS APP,MXK_GROUP_PRIVILEGES GP,MXK_GROUPS G WHERE APP.ID=GP.APPID - AND GP.GROUPID IN( - SELECT - G.ID - FROM - `MXK_GROUPS` G - WHERE - G.ID='ALL_USER_GROUP' - OR G.ID IN( + AND GP.GROUPID=G.ID + AND ( + G.ID='ROLE_ALL_USER' + OR G.ID IN( SELECT GM.GROUPID FROM MXK_GROUP_MEMBER GM,MXK_USERINFO U - WHERE 1 = 1 + WHERE GM.MEMBERID = U.ID AND U.ID = #{userId} AND U.USERNAME = #{username} - AND GM.MEMBERID = U.ID ) ) diff --git a/maxkey-protocols/maxkey-protocol-authorize/src/main/java/org/maxkey/authz/singlelogout/SamlSingleLogout.java b/maxkey-protocols/maxkey-protocol-authorize/src/main/java/org/maxkey/authz/singlelogout/SamlSingleLogout.java index 3ef02284b..b3f84f49a 100644 --- a/maxkey-protocols/maxkey-protocol-authorize/src/main/java/org/maxkey/authz/singlelogout/SamlSingleLogout.java +++ b/maxkey-protocols/maxkey-protocol-authorize/src/main/java/org/maxkey/authz/singlelogout/SamlSingleLogout.java @@ -7,6 +7,12 @@ import org.maxkey.domain.apps.Apps; import org.maxkey.util.DateUtils; import org.springframework.security.core.Authentication; +/** + * SamlSingleLogout + * https://apereo.github.io/cas/6.2.x/installation/Logout-Single-Signout.html + * @author Crystal.Sea + * + */ public class SamlSingleLogout extends SingleLogout{ /** diff --git a/maxkey-web-manage/src/main/java/org/maxkey/web/contorller/GroupMemberController.java b/maxkey-web-manage/src/main/java/org/maxkey/web/contorller/GroupMemberController.java index 1db2b69ed..fba994a73 100644 --- a/maxkey-web-manage/src/main/java/org/maxkey/web/contorller/GroupMemberController.java +++ b/maxkey-web-manage/src/main/java/org/maxkey/web/contorller/GroupMemberController.java @@ -87,7 +87,7 @@ public class GroupMemberController { @ResponseBody public JpaPageResults queryMemberInGroup(@ModelAttribute("groupMember") GroupMember groupMember) { _logger.debug("groupMember : "+groupMember); - if(groupMember.getGroupId()==null||groupMember.getGroupId().equals("")||groupMember.getGroupId().equals("ALL_USER_GROUP")){ + if(groupMember.getGroupId()==null||groupMember.getGroupId().equals("")||groupMember.getGroupId().equals("ROLE_ALL_USER")){ return groupMemberService.queryPageResults("allMemberInGroup",groupMember); }else{ return groupMemberService.queryPageResults("memberInGroup",groupMember); diff --git a/maxkey-web-maxkey/src/main/java/org/maxkey/web/interceptor/HistoryLoginAppAdapter.java b/maxkey-web-maxkey/src/main/java/org/maxkey/web/interceptor/HistoryLoginAppAdapter.java index 1e6d0f1ce..dabf42c60 100644 --- a/maxkey-web-maxkey/src/main/java/org/maxkey/web/interceptor/HistoryLoginAppAdapter.java +++ b/maxkey-web-maxkey/src/main/java/org/maxkey/web/interceptor/HistoryLoginAppAdapter.java @@ -19,6 +19,8 @@ package org.maxkey.web.interceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + +import org.maxkey.authn.SigninPrincipal; import org.maxkey.authz.endpoint.AuthorizeBaseEndpoint; import org.maxkey.domain.HistoryLoginApps; import org.maxkey.domain.UserInfo; @@ -31,6 +33,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.stereotype.Component; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; @@ -46,6 +50,28 @@ public class HistoryLoginAppAdapter extends HandlerInterceptorAdapter { @Qualifier("appsService") protected AppsService appsService; + /** + * 判断应用访问权限 + */ + @Override + public boolean preHandle(HttpServletRequest request, + HttpServletResponse response, Object handler) + throws Exception { + _logger.debug("preHandle"); + final Apps app = (Apps)WebContext.getAttribute(AuthorizeBaseEndpoint.class.getName()); + Authentication authentication = WebContext.getAuthentication(); + if(authentication.getPrincipal() instanceof SigninPrincipal) { + SigninPrincipal signinPrincipal = (SigninPrincipal)authentication.getPrincipal() ; + if(signinPrincipal.getGrantedAuthorityApps().contains(new SimpleGrantedAuthority(app.getId()))) { + _logger.trace("preHandle have authority access " + app); + return true; + } + } + _logger.debug("preHandle not have authority access " + app); + return false; + } + + /** * postHandle . * @see org.springframework.web.servlet.handler.HandlerInterceptorAdapter#preHandle(