From b4f122865bef95c2eaf9511df98583d56ab21640 Mon Sep 17 00:00:00 2001 From: jeesun Date: Fri, 17 May 2019 11:20:40 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=82=B9=E5=87=BB?= =?UTF-8?q?=E4=BE=A7=E8=BE=B9=E6=A0=8F=E8=8F=9C=E5=8D=95=E3=80=81=E6=A0=87?= =?UTF-8?q?=E9=A2=98=E4=B8=8D=E6=94=B9=E5=8F=98=E7=9A=84bug=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/src/main/resources/templates/vue/index.html | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/web/src/main/resources/templates/vue/index.html b/web/src/main/resources/templates/vue/index.html index 6399774..5f4d104 100644 --- a/web/src/main/resources/templates/vue/index.html +++ b/web/src/main/resources/templates/vue/index.html @@ -198,7 +198,7 @@ 'fa-outdent': true }, inOrOutKey: 1, - menuData: [], + menuData: [[${menuData}]], dynamicTags: ['标签一', '标签二', '标签三'], inputVisible: false, inputValue: '', @@ -226,7 +226,7 @@ } }, mounted: function () { - this.loadMenuData(); + //this.loadMenuData(); this.iframeHeight = document.body.clientHeight - 120; }, methods: { @@ -283,7 +283,7 @@ this.addTab(123, '登录', '/vue/demo', true); }, addTab: function (id, title, url, closable) { - //console.log("id=" + id + ",title=" + title + ",url=" + url); + console.log("id=" + id + ",title=" + title + ",url=" + url); let targetName = id + ''; let tabs = this.editableTabs; let activeName = this.editableTabsValue; @@ -331,11 +331,11 @@ }, changeTitle: function (id) { let found = false; - for (let i = 0; i < this.menuData.length; i++) { + for (let i = 0, len = this.menuData.length; i < len; i++) { let menuItem = this.menuData[i]; - for (let j = 0; j < menuItem.children.length; j++) { + for (let j = 0, childrenLen = menuItem.children.length; j < childrenLen; j++) { let subMenuItem = menuItem.children[j]; - if (subMenuItem['id'] == id) { + if (subMenuItem['id'] === id) { this.parentPath = menuItem['name']; this.childPath = subMenuItem['name']; found = true; -- Gitee From 8637fb1f989a6344ac63b1d4f091973a1b7a5b4c Mon Sep 17 00:00:00 2001 From: jeesun Date: Fri, 17 May 2019 11:21:29 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E7=A7=BB=E9=99=A4spring=20boot=20jwt?= =?UTF-8?q?=EF=BC=9B=E4=BD=BF=E7=94=A8jetty=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/pom.xml | 22 ++++++++++++++-------- common/pom.xml | 7 +++++++ pom.xml | 26 +++++++++++++++++--------- web/pom.xml | 19 +++++++++++++------ 4 files changed, 51 insertions(+), 23 deletions(-) diff --git a/api/pom.xml b/api/pom.xml index d961f08..6e63b6c 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -64,17 +64,17 @@ org.springframework.boot spring-boot-starter-web - + - + com.github.ulisesbocchio jasypt-spring-boot-starter @@ -86,10 +86,10 @@ test - + @@ -123,10 +123,10 @@ org.springframework.boot spring-boot-starter-data-rest - + @@ -360,6 +360,12 @@ 1.12.5 + + javax.servlet + javax.servlet-api + provided + + com.simon common diff --git a/common/pom.xml b/common/pom.xml index 29cda60..05487af 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -194,6 +194,13 @@ org.quartz-scheduler quartz-jobs + + + javax.servlet + javax.servlet-api + provided + + diff --git a/pom.xml b/pom.xml index ed3cc24..c20a42a 100644 --- a/pom.xml +++ b/pom.xml @@ -65,11 +65,11 @@ spring-cloud-starter-security 1.2.3.RELEASE - + org.springframework.cloud spring-cloud-starter-zuul @@ -111,16 +111,22 @@ org.springframework.boot spring-boot-starter-web ${spring-boot.version} - + + + + org.springframework.boot + spring-boot-starter-jetty + ${spring-boot.version} com.github.ulisesbocchio @@ -200,11 +206,6 @@ springfox-swagger-ui ${swagger2.version} - - - - - @@ -454,6 +455,13 @@ 3.14.1 + + javax.servlet + javax.servlet-api + 4.0.1 + provided + + com.alibaba easyexcel diff --git a/web/pom.xml b/web/pom.xml index 6df6a55..d2c8d49 100644 --- a/web/pom.xml +++ b/web/pom.xml @@ -64,17 +64,17 @@ org.springframework.boot spring-boot-starter-web - + - + com.github.ulisesbocchio jasypt-spring-boot-starter @@ -86,10 +86,10 @@ test - + @@ -410,6 +410,13 @@ vue 2.6.9 + + + javax.servlet + javax.servlet-api + provided + + com.alibaba -- Gitee From f563c5a2802f0be740935e0a85821ced3a0d44a6 Mon Sep 17 00:00:00 2001 From: jeesun Date: Fri, 17 May 2019 15:09:31 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E8=A7=A3=E5=86=B3=E6=82=AC=E8=80=8C?= =?UTF-8?q?=E6=9C=AA=E5=86=B3=E7=9A=84=E7=99=BB=E5=BD=95=E5=A4=B1=E8=B4=A5?= =?UTF-8?q?=E6=8F=90=E7=A4=BA=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../config/AuthExceptionEntryPoint.java | 44 ------------------- .../config/CustomLoginAuthProvider.java | 24 +++++----- .../common/config/WebSecurityConfig.java | 9 +++- .../handler/CustomAccessDeniedHandler.java | 44 ------------------- .../CustomAuthenticationFailureHandler.java | 24 ++++++++++ .../oauth/UsernamePasswordAuthenticator.java | 20 ++++----- web/src/main/resources/templates/login.html | 6 +++ 7 files changed, 60 insertions(+), 111 deletions(-) delete mode 100644 web/src/main/java/com/simon/common/config/AuthExceptionEntryPoint.java delete mode 100644 web/src/main/java/com/simon/common/handler/CustomAccessDeniedHandler.java create mode 100644 web/src/main/java/com/simon/common/handler/CustomAuthenticationFailureHandler.java diff --git a/web/src/main/java/com/simon/common/config/AuthExceptionEntryPoint.java b/web/src/main/java/com/simon/common/config/AuthExceptionEntryPoint.java deleted file mode 100644 index d2d22cd..0000000 --- a/web/src/main/java/com/simon/common/config/AuthExceptionEntryPoint.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.simon.common.config; - -import lombok.extern.slf4j.Slf4j; -import org.codehaus.jackson.map.ObjectMapper; -import org.springframework.security.core.AuthenticationException; -import org.springframework.security.web.AuthenticationEntryPoint; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.util.LinkedHashMap; -import java.util.Map; - -/** - * 自定义AuthenticationEntryPoint实现类 - * @author simon - * @create 2018-05-31 18:18 - **/ -@Slf4j -public class AuthExceptionEntryPoint implements AuthenticationEntryPoint { - - @Override - public void commence(HttpServletRequest request, HttpServletResponse response, - AuthenticationException authException) - throws ServletException { - response.setContentType("application/json"); - response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); - - log.error(authException.getMessage()); - Map map = new LinkedHashMap<>(); - map.put("code", response.getStatus()); - map.put("message", authException.getMessage()); - map.put("data", null); - //map.put("path", request.getServletPath()); - //map.put("timestamp", String.valueOf(new Date().getTime())); - - try { - ObjectMapper mapper = new ObjectMapper(); - mapper.writeValue(response.getOutputStream(), map); - } catch (Exception e) { - throw new ServletException(); - } - } -} diff --git a/web/src/main/java/com/simon/common/config/CustomLoginAuthProvider.java b/web/src/main/java/com/simon/common/config/CustomLoginAuthProvider.java index 0837177..09b7eea 100644 --- a/web/src/main/java/com/simon/common/config/CustomLoginAuthProvider.java +++ b/web/src/main/java/com/simon/common/config/CustomLoginAuthProvider.java @@ -4,21 +4,22 @@ import com.simon.common.domain.UserEntity; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.MessageSource; -import org.springframework.security.authentication.AuthenticationProvider; -import org.springframework.security.authentication.DisabledException; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.authentication.*; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; -import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; +import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Component; import java.util.Collection; import java.util.Locale; +/** + * @author simon + * @date 2019-05-17 + */ @Slf4j @Component public class CustomLoginAuthProvider implements AuthenticationProvider { @@ -28,6 +29,9 @@ public class CustomLoginAuthProvider implements AuthenticationProvider { @Autowired private MessageSource messageSource; + @Autowired + private PasswordEncoder encoder; + private Locale locale = AppConfig.getLocale(); @Override @@ -37,17 +41,15 @@ public class CustomLoginAuthProvider implements AuthenticationProvider { String username = authentication.getName(); String password = (String) authentication.getCredentials(); UserEntity userEntity = (UserEntity) userDetailsService.loadUserByUsername(username); - if (null == userEntity){ + if (null == userEntity) { throw new UsernameNotFoundException(messageSource.getMessage("usernameNotFound", null, locale)); } - if (!userEntity.isEnabled()){ + if (!userEntity.isEnabled()) { throw new DisabledException(messageSource.getMessage("accountDisabled", null, locale)); } - BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(11); - - if(!encoder.matches(password, userEntity.getPassword())){ - throw new InvalidGrantException(messageSource.getMessage("passwordError", null, locale)); + if (!encoder.matches(password, userEntity.getPassword())) { + throw new BadCredentialsException(messageSource.getMessage("passwordError", null, locale)); } Collection authorities = userEntity.getAuthorities(); diff --git a/web/src/main/java/com/simon/common/config/WebSecurityConfig.java b/web/src/main/java/com/simon/common/config/WebSecurityConfig.java index 5e90530..c27dc08 100644 --- a/web/src/main/java/com/simon/common/config/WebSecurityConfig.java +++ b/web/src/main/java/com/simon/common/config/WebSecurityConfig.java @@ -10,8 +10,10 @@ import org.springframework.security.config.annotation.method.configuration.Enabl import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.web.authentication.AuthenticationFailureHandler; import javax.sql.DataSource; +import java.net.URLEncoder; /** * Created by simon on 2017/2/18. @@ -32,6 +34,9 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private AuthSuccessHandler authSuccessHandler; + @Autowired + private AuthenticationFailureHandler customAuthenticationFailureHandler; + @Override @Bean public AuthenticationManager authenticationManagerBean() @@ -101,6 +106,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { .and() .formLogin() .successHandler(authSuccessHandler) + .failureHandler(customAuthenticationFailureHandler) .loginPage("/login").permitAll() .defaultSuccessUrl("/index") .and() @@ -122,7 +128,6 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { http .sessionManagement() .maximumSessions(1) - .expiredUrl("/login?result=loginAnotherLocation"); + .expiredUrl("/login?errMsg=" + URLEncoder.encode("您已在其他地方登录", "utf-8")); } - } diff --git a/web/src/main/java/com/simon/common/handler/CustomAccessDeniedHandler.java b/web/src/main/java/com/simon/common/handler/CustomAccessDeniedHandler.java deleted file mode 100644 index e6f736a..0000000 --- a/web/src/main/java/com/simon/common/handler/CustomAccessDeniedHandler.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.simon.common.handler; - -import com.fasterxml.jackson.databind.ObjectMapper; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.access.AccessDeniedException; -import org.springframework.security.web.access.AccessDeniedHandler; -import org.springframework.stereotype.Component; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.Date; -import java.util.LinkedHashMap; -import java.util.Map; - -/** - * 自定义AccessDeniedHandler实现类 - * - * @author simon - * @create 2018-05-31 18:19 - **/ - -@Slf4j -@Component("customAccessDeniedHandler") -public class CustomAccessDeniedHandler implements AccessDeniedHandler { - - @Autowired - private ObjectMapper objectMapper; - - @Override - public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException { - response.setContentType("application/json;charset=UTF-8"); - Map map = new LinkedHashMap<>(); - map.put("error", "400"); - map.put("message", accessDeniedException.getMessage()); - map.put("path", request.getServletPath()); - map.put("timestamp", String.valueOf(new Date().getTime())); - response.setContentType("application/json"); - response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); - response.getWriter().write(objectMapper.writeValueAsString(map)); - } -} \ No newline at end of file diff --git a/web/src/main/java/com/simon/common/handler/CustomAuthenticationFailureHandler.java b/web/src/main/java/com/simon/common/handler/CustomAuthenticationFailureHandler.java new file mode 100644 index 0000000..8000c93 --- /dev/null +++ b/web/src/main/java/com/simon/common/handler/CustomAuthenticationFailureHandler.java @@ -0,0 +1,24 @@ +package com.simon.common.handler; + +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; +import org.springframework.stereotype.Component; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.net.URLEncoder; + +/** + * @author simon + */ +@Component("customAuthenticationFailureHandler") +public class CustomAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler { + @Override + public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, + AuthenticationException exception) throws IOException, ServletException { + super.setDefaultFailureUrl("/login?errMsg=" + URLEncoder.encode(exception.getMessage(), "utf-8")); + super.onAuthenticationFailure(request, response, exception); + } +} diff --git a/web/src/main/java/com/simon/common/plugins/oauth/UsernamePasswordAuthenticator.java b/web/src/main/java/com/simon/common/plugins/oauth/UsernamePasswordAuthenticator.java index 2833d49..2cea0ce 100644 --- a/web/src/main/java/com/simon/common/plugins/oauth/UsernamePasswordAuthenticator.java +++ b/web/src/main/java/com/simon/common/plugins/oauth/UsernamePasswordAuthenticator.java @@ -14,7 +14,7 @@ import org.springframework.context.annotation.Primary; import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; -import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; +import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Component; import java.util.List; @@ -46,15 +46,15 @@ public class UsernamePasswordAuthenticator extends AbstractPreparableIntegration private final static String PASSWORD_AUTH_TYPE = "password"; - public UsernamePasswordAuthenticator(){ + public UsernamePasswordAuthenticator() { sqlLoadUserByPhone = "select id,username,password,enabled,phone,email,address,birth,age,head_photo,person_brief,sex from t_users where phone=?"; sqlLoadUserByEmail = "select id,username,password,enabled,phone,email,address,birth,age,head_photo,person_brief,sex from t_users where email=?"; sqlLoadUserByName = "select id,username,password,enabled,phone,email,address,birth,age,head_photo,person_brief,sex from t_users where username=?"; sqlLoadAuthorities = "select user_id,authority from t_authorities where user_id = ?"; - myUserDetailsRowMapper = (rs, i) -> new UserEntity(rs.getLong(1), rs.getString(2), rs.getString(3), rs.getBoolean(4), rs.getString("phone"), rs.getString("email"),rs.getString("address"), DateUtil.dateToLocalDate(rs.getDate("birth")), rs.getInt("age"), rs.getString("head_photo"), rs.getString("person_brief"), rs.getBoolean("sex")); + myUserDetailsRowMapper = (rs, i) -> new UserEntity(rs.getLong(1), rs.getString(2), rs.getString(3), rs.getBoolean(4), rs.getString("phone"), rs.getString("email"), rs.getString("address"), DateUtil.dateToLocalDate(rs.getDate("birth")), rs.getInt("age"), rs.getString("head_photo"), rs.getString("person_brief"), rs.getBoolean("sex")); - authorityRowMapper = (rs,i) -> { + authorityRowMapper = (rs, i) -> { Authority authority = new Authority(); authority.setUserId(rs.getLong(1)); authority.setAuthority(rs.getString(2)); @@ -65,13 +65,13 @@ public class UsernamePasswordAuthenticator extends AbstractPreparableIntegration @Override public UserEntity authenticate(IntegrationAuthentication integrationAuthentication) { log.info("password authenticate"); - try{ + try { UserEntity userFromQuery = null; - if(ValidUtil.isEmail(integrationAuthentication.getUsername())){ + if (ValidUtil.isEmail(integrationAuthentication.getUsername())) { userFromQuery = jdbcTemplate.queryForObject(sqlLoadUserByEmail, myUserDetailsRowMapper, integrationAuthentication.getUsername()); - }else if(ValidUtil.isMobile(integrationAuthentication.getUsername())){ + } else if (ValidUtil.isMobile(integrationAuthentication.getUsername())) { userFromQuery = jdbcTemplate.queryForObject(sqlLoadUserByPhone, myUserDetailsRowMapper, integrationAuthentication.getUsername()); - }else{ + } else { //userFromQuery = jdbcTemplate.queryForObject(sqlLoadUserByName, myUserDetailsRowMapper, integrationAuthentication.getUsername()); throw new BusinessException("不支持的登录方式"); } @@ -81,9 +81,9 @@ public class UsernamePasswordAuthenticator extends AbstractPreparableIntegration log.info("得到其权限:{}", authorities); return new UserEntity(userFromQuery.getId(), userFromQuery.getUsername(), userFromQuery.getPassword(), userFromQuery.isEnabled(), userFromQuery.getPhone(), userFromQuery.getEmail(), userFromQuery.getAddress(), userFromQuery.getBirth(), userFromQuery.getAge(), userFromQuery.getHeadPhoto(), userFromQuery.getPersonBrief(), userFromQuery.getSex(), authorities); - }catch (EmptyResultDataAccessException e){ + } catch (EmptyResultDataAccessException e) { log.info("查询结果集为空:{}", integrationAuthentication.getUsername()); - throw new InvalidGrantException(messageSource.getMessage("usernameNotFound", null, locale)); + throw new UsernameNotFoundException(messageSource.getMessage("usernameNotFound", null, locale)); } } diff --git a/web/src/main/resources/templates/login.html b/web/src/main/resources/templates/login.html index 01c02a5..22ed029 100644 --- a/web/src/main/resources/templates/login.html +++ b/web/src/main/resources/templates/login.html @@ -42,6 +42,9 @@ background-size: cover; } + .error { + color: red; + } @@ -49,6 +52,9 @@

+
+
+
-- Gitee