From 82eafa29bb9855f2dbaa647a6b38059579e6c276 Mon Sep 17 00:00:00 2001 From: fanxingmeng Date: Thu, 26 Jan 2023 20:06:32 +0800 Subject: [PATCH 1/5] jwt-protocol --- .../protocol/jwt/config/SecurityConfig.java | 68 ++++++++ .../jwt/constant/ProtocolConstants.java | 18 ++ .../jwt/filter/JwtAccessDeniedHandler.java | 56 +++++++ .../filter/JwtAuthenticationEntryPoint.java | 56 +++++++ .../jwt/filter/JwtAuthenticationFilter.java | 70 ++++++++ .../jwt/filter/JwtLogoutSuccessHandler.java | 60 +++++++ .../jwt/filter/LoginFailureHandler.java | 52 ++++++ .../jwt/filter/LoginSuccessHandler.java | 63 +++++++ .../protocol/jwt/model/JwtResult.java | 55 ++++++ .../userdetails/UserDetailsServiceImpl.java | 132 +++++++++++++++ .../employee/protocol/jwt/util/JwtUtil.java | 157 ++++++++++++++++++ 11 files changed, 787 insertions(+) create mode 100644 eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/config/SecurityConfig.java create mode 100644 eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/JwtAccessDeniedHandler.java create mode 100644 eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/JwtAuthenticationEntryPoint.java create mode 100644 eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/JwtAuthenticationFilter.java create mode 100644 eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/JwtLogoutSuccessHandler.java create mode 100644 eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/LoginFailureHandler.java create mode 100644 eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/LoginSuccessHandler.java create mode 100644 eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/model/JwtResult.java create mode 100644 eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/userdetails/UserDetailsServiceImpl.java create mode 100644 eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/util/JwtUtil.java diff --git a/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/config/SecurityConfig.java b/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/config/SecurityConfig.java new file mode 100644 index 00000000..1a4c1234 --- /dev/null +++ b/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/config/SecurityConfig.java @@ -0,0 +1,68 @@ +/* + * eiam-protocol-jwt - Employee Identity and Access Management Program + * Copyright © 2020-2022 TopIAM (support@topiam.cn) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package cn.topiam.employee.protocol.jwt.config; + +import javax.annotation.Resource; + +import org.springframework.context.annotation.Bean; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +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.config.http.SessionCreationPolicy; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; + +import cn.topiam.employee.protocol.jwt.filter.JwtAccessDeniedHandler; +import cn.topiam.employee.protocol.jwt.filter.JwtAuthenticationEntryPoint; +import cn.topiam.employee.protocol.jwt.filter.JwtAuthenticationFilter; +import cn.topiam.employee.protocol.jwt.filter.LoginSuccessHandler; +import cn.topiam.employee.protocol.jwt.userdetails.UserDetailsServiceImpl; + +@EnableWebSecurity +public class SecurityConfig extends WebSecurityConfigurerAdapter { + + @Resource + private UserDetailsServiceImpl userDetailsService; + + @Override + protected void configure(HttpSecurity http) throws Exception { + http.authorizeRequests() + // 允许访问 + .antMatchers("/login").permitAll().anyRequest().authenticated() // 其他请求拦截 + .and().csrf().disable() //关闭csrf + .addFilterBefore(new JwtAuthenticationFilter(), + UsernamePasswordAuthenticationFilter.class) + .formLogin().successHandler(new LoginSuccessHandler()).and().sessionManagement() + .sessionCreationPolicy(SessionCreationPolicy.STATELESS) //禁用session + // 异常处理器 + .and().exceptionHandling().authenticationEntryPoint(new JwtAuthenticationEntryPoint()) + .accessDeniedHandler(new JwtAccessDeniedHandler()); + } + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder()); + } + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } +} diff --git a/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/constant/ProtocolConstants.java b/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/constant/ProtocolConstants.java index 72f1127f..9793d222 100644 --- a/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/constant/ProtocolConstants.java +++ b/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/constant/ProtocolConstants.java @@ -17,6 +17,7 @@ */ package cn.topiam.employee.protocol.jwt.constant; +import io.jsonwebtoken.SignatureAlgorithm; import static cn.topiam.employee.common.constants.AuthorizeConstants.AUTHORIZE_PATH; import static cn.topiam.employee.common.constants.ProtocolConstants.APP_CODE_VARIABLE; @@ -33,4 +34,21 @@ public class ProtocolConstants { */ public static final String IDP_JWT_SSO_INITIATOR = AUTHORIZE_PATH + "/jwt/" + APP_CODE_VARIABLE + "/initiator"; + /** + * jwt 加密算法 + */ + public static final SignatureAlgorithm SIGNATURE_ALGORITHM = SignatureAlgorithm.HS256; + + /** + * jwt 请求头 + */ + public static final String REQUEST_HEADER = "Authorization"; + /** + * claim 相关 + */ + public static final String CLAIM_KEY_USERNAME = "username"; + + public static final String CLAIM_KEY_LOGINTIME = "loginTime"; + + public static final String CLAIM_KEY_CREATED = "createTime"; } diff --git a/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/JwtAccessDeniedHandler.java b/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/JwtAccessDeniedHandler.java new file mode 100644 index 00000000..d0d9a687 --- /dev/null +++ b/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/JwtAccessDeniedHandler.java @@ -0,0 +1,56 @@ +/* + * eiam-protocol-jwt - Employee Identity and Access Management Program + * Copyright © 2020-2022 TopIAM (support@topiam.cn) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package cn.topiam.employee.protocol.jwt.filter; + +import java.io.IOException; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.web.access.AccessDeniedHandler; +import org.springframework.stereotype.Component; + +import cn.hutool.json.JSONUtil; +import cn.topiam.employee.protocol.jwt.model.JwtResult; + +@Component +public class JwtAccessDeniedHandler implements AccessDeniedHandler { + public JwtAccessDeniedHandler() { + + } + + @Override + public void handle(HttpServletRequest request, HttpServletResponse response, + AccessDeniedException accessDeniedException) throws IOException { + + response.setContentType("application/json;charset=UTF-8"); + response.setStatus(HttpServletResponse.SC_FORBIDDEN); + + ServletOutputStream outputStream = response.getOutputStream(); + + JwtResult result = JwtResult.fail(accessDeniedException.getMessage()); + + outputStream.write(JSONUtil.toJsonStr(result).getBytes("UTF-8")); + + outputStream.flush(); + outputStream.close(); + + } +} diff --git a/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/JwtAuthenticationEntryPoint.java b/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/JwtAuthenticationEntryPoint.java new file mode 100644 index 00000000..9c94ba96 --- /dev/null +++ b/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/JwtAuthenticationEntryPoint.java @@ -0,0 +1,56 @@ +/* + * eiam-protocol-jwt - Employee Identity and Access Management Program + * Copyright © 2020-2022 TopIAM (support@topiam.cn) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package cn.topiam.employee.protocol.jwt.filter; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.stereotype.Component; + +import cn.hutool.json.JSONUtil; +import cn.topiam.employee.protocol.jwt.model.JwtResult; + +@Component +public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint { + public JwtAuthenticationEntryPoint() { + + } + + @Override + public void commence(HttpServletRequest request, HttpServletResponse response, + AuthenticationException authException) throws IOException, + ServletException { + + response.setContentType("application/json;charset=UTF-8"); + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + ServletOutputStream outputStream = response.getOutputStream(); + + JwtResult result = JwtResult.fail("请先登录"); + + outputStream.write(JSONUtil.toJsonStr(result).getBytes("UTF-8")); + + outputStream.flush(); + outputStream.close(); + } +} diff --git a/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/JwtAuthenticationFilter.java b/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/JwtAuthenticationFilter.java new file mode 100644 index 00000000..100c9c48 --- /dev/null +++ b/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/JwtAuthenticationFilter.java @@ -0,0 +1,70 @@ +/* + * eiam-protocol-jwt - Employee Identity and Access Management Program + * Copyright © 2020-2022 TopIAM (support@topiam.cn) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package cn.topiam.employee.protocol.jwt.filter; + +import java.io.IOException; + +import javax.annotation.Resource; +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; +import org.springframework.web.filter.OncePerRequestFilter; + +import cn.topiam.employee.core.security.userdetails.UserDetails; +import cn.topiam.employee.protocol.jwt.constant.ProtocolConstants; +import cn.topiam.employee.protocol.jwt.userdetails.UserDetailsServiceImpl; +import cn.topiam.employee.protocol.jwt.util.JwtUtil; + +public class JwtAuthenticationFilter extends OncePerRequestFilter { + @Resource + private UserDetailsServiceImpl userDetailsService; + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, + FilterChain filterChain) throws ServletException, IOException { + // 请求头中获取token信息 + String token = request.getHeader(ProtocolConstants.REQUEST_HEADER); + if (!token.isBlank()) { + // 利用token获取用户名 + String username = JwtUtil.getUserNameFromToken(token); + // token存在用户但未登陆 + // SecurityContextHolder.getContext().getAuthentication() 获取上下文对象中认证信息 + if (null != username + && null == SecurityContextHolder.getContext().getAuthentication()) { + // 自定义数据源获取用户信息 + UserDetails userDetails = userDetailsService.loadUserByUsername(username); + // 验证token是否有效 验证token用户名和存储的用户名是否一致以及是否在有效期内, 重新设置用户对象 + if (JwtUtil.validateToken(token, userDetails)) { + // 重新将用户信息封装到UsernamePasswordAuthenticationToken + UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken( + userDetails, null, userDetails.getAuthorities()); + authenticationToken + .setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); + // 将信息存入上下文对象 + SecurityContextHolder.getContext().setAuthentication(authenticationToken); + } + } + } + filterChain.doFilter(request, response); + } +} diff --git a/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/JwtLogoutSuccessHandler.java b/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/JwtLogoutSuccessHandler.java new file mode 100644 index 00000000..3de8327f --- /dev/null +++ b/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/JwtLogoutSuccessHandler.java @@ -0,0 +1,60 @@ +/* + * eiam-protocol-jwt - Employee Identity and Access Management Program + * Copyright © 2020-2022 TopIAM (support@topiam.cn) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package cn.topiam.employee.protocol.jwt.filter; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.security.core.Authentication; +import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; +import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler; +import org.springframework.stereotype.Component; + +import cn.hutool.json.JSONUtil; +import cn.topiam.employee.protocol.jwt.constant.ProtocolConstants; +import cn.topiam.employee.protocol.jwt.model.JwtResult; + +@Component +public class JwtLogoutSuccessHandler implements LogoutSuccessHandler { + + @Override + public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, + Authentication authentication) throws IOException, + ServletException { + + if (authentication != null) { + new SecurityContextLogoutHandler().logout(request, response, authentication); + } + + response.setContentType("application/json;charset=UTF-8"); + ServletOutputStream outputStream = response.getOutputStream(); + + response.setHeader(ProtocolConstants.REQUEST_HEADER, ""); + + JwtResult result = JwtResult.succ(""); + + outputStream.write(JSONUtil.toJsonStr(result).getBytes("UTF-8")); + + outputStream.flush(); + outputStream.close(); + } +} diff --git a/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/LoginFailureHandler.java b/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/LoginFailureHandler.java new file mode 100644 index 00000000..296e2c1c --- /dev/null +++ b/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/LoginFailureHandler.java @@ -0,0 +1,52 @@ +/* + * eiam-protocol-jwt - Employee Identity and Access Management Program + * Copyright © 2020-2022 TopIAM (support@topiam.cn) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package cn.topiam.employee.protocol.jwt.filter; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.AuthenticationFailureHandler; + +import cn.hutool.json.JSONUtil; +import cn.topiam.employee.protocol.jwt.model.JwtResult; + +/** + * 登录失败处理类 + */ +public class LoginFailureHandler implements AuthenticationFailureHandler { + + @Override + public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, + AuthenticationException exception) throws IOException, + ServletException { + response.setContentType("application/json;charset=UTF-8"); + ServletOutputStream outputStream = response.getOutputStream(); + + JwtResult result = JwtResult.fail("用户名或密码错误"); + + outputStream.write(JSONUtil.toJsonStr(result).getBytes("UTF-8")); + + outputStream.flush(); + outputStream.close(); + } +} diff --git a/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/LoginSuccessHandler.java b/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/LoginSuccessHandler.java new file mode 100644 index 00000000..5d63a732 --- /dev/null +++ b/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/LoginSuccessHandler.java @@ -0,0 +1,63 @@ +/* + * eiam-protocol-jwt - Employee Identity and Access Management Program + * Copyright © 2020-2022 TopIAM (support@topiam.cn) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package cn.topiam.employee.protocol.jwt.filter; + +import java.io.IOException; + +import javax.annotation.Resource; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.security.core.Authentication; +import org.springframework.security.web.authentication.AuthenticationSuccessHandler; + +import cn.hutool.json.JSONUtil; +import cn.topiam.employee.core.security.userdetails.UserDetails; +import cn.topiam.employee.protocol.jwt.constant.ProtocolConstants; +import cn.topiam.employee.protocol.jwt.model.JwtResult; +import cn.topiam.employee.protocol.jwt.userdetails.UserDetailsServiceImpl; +import cn.topiam.employee.protocol.jwt.util.JwtUtil; + +/** + * 登录成功处理类 + */ +public class LoginSuccessHandler implements AuthenticationSuccessHandler { + @Resource + private UserDetailsServiceImpl userDetailsService; + + @Override + public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, + Authentication authentication) throws IOException, + ServletException { + response.setContentType("application/json;charset=UTF-8"); + ServletOutputStream outputStream = response.getOutputStream(); + + // 生成jwt返回 + String username = authentication.getName(); + UserDetails userDetails = userDetailsService.loadUserByUsername(username); + String jwt = JwtUtil.createToken(userDetails); + response.setHeader(ProtocolConstants.REQUEST_HEADER, jwt); + + JwtResult result = JwtResult.succ(""); + outputStream.write(JSONUtil.toJsonStr(result).getBytes("UTF-8")); + outputStream.flush(); + outputStream.close(); + } +} diff --git a/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/model/JwtResult.java b/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/model/JwtResult.java new file mode 100644 index 00000000..5714f4eb --- /dev/null +++ b/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/model/JwtResult.java @@ -0,0 +1,55 @@ +/* + * eiam-protocol-jwt - Employee Identity and Access Management Program + * Copyright © 2020-2022 TopIAM (support@topiam.cn) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package cn.topiam.employee.protocol.jwt.model; + +import java.io.Serializable; + +import lombok.Data; + +@Data +public class JwtResult implements Serializable { + + private int code; + private String msg; + private Object data; + + public static JwtResult succ(Object data) { + return succ(200, "操作成功", data); + } + + public static JwtResult succ(int code, String msg, Object data) { + JwtResult r = new JwtResult(); + r.setCode(code); + r.setMsg(msg); + r.setData(data); + return r; + } + + public static JwtResult fail(String msg) { + return fail(400, msg, null); + } + + public static JwtResult fail(int code, String msg, Object data) { + JwtResult r = new JwtResult(); + r.setCode(code); + r.setMsg(msg); + r.setData(data); + return r; + } + +} diff --git a/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/userdetails/UserDetailsServiceImpl.java b/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/userdetails/UserDetailsServiceImpl.java new file mode 100644 index 00000000..a1970976 --- /dev/null +++ b/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/userdetails/UserDetailsServiceImpl.java @@ -0,0 +1,132 @@ +/* + * eiam-protocol-jwt - Employee Identity and Access Management Program + * Copyright © 2020-2022 TopIAM (support@topiam.cn) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package cn.topiam.employee.protocol.jwt.userdetails; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Optional; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.authentication.AccountExpiredException; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Component; +import org.springframework.util.ObjectUtils; + +import cn.topiam.employee.common.entity.account.UserDetailEntity; +import cn.topiam.employee.common.entity.account.UserEntity; +import cn.topiam.employee.common.enums.UserStatus; +import cn.topiam.employee.common.enums.UserType; +import cn.topiam.employee.common.repository.account.UserDetailRepository; +import cn.topiam.employee.common.repository.account.UserRepository; +import cn.topiam.employee.core.security.authorization.Roles; +import cn.topiam.employee.core.security.userdetails.UserDetails; +import cn.topiam.employee.core.security.userdetails.UserDetailsService; + +@Component(value = "userDetailsService") +public class UserDetailsServiceImpl implements UserDetailsService { + + private static final Logger logger = LoggerFactory.getLogger(UserDetailsServiceImpl.class); + + /** + * Locates the user based on the username. In the actual implementation, the search + * may possibly be case sensitive, or case insensitive depending on how the + * implementation instance is configured. In this case, the UserDetails + * object that comes back may have a username that is of a different case than what + * was actually requested.. + * + * @param username the username identifying the user whose data is required. + * @return a fully populated user record (never null) + * @throws UsernameNotFoundException if the user could not be found or the user has no + * GrantedAuthority + */ + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + // 状态相关 + boolean enabled = true, accountNonLocked = true; + // 权限 + Collection authorities = new ArrayList<>(); + UserEntity user; + // 用户名 + user = userRepository.findByUsername(username); + if (ObjectUtils.isEmpty(user)) { + // 手机号 + user = userRepository.findByPhone(username); + if (ObjectUtils.isEmpty(user)) { + // 邮箱 + user = userRepository.findByEmail(username); + } + } + //不存在该用户 + if (ObjectUtils.isEmpty(user)) { + logger.info("根据用户名、手机号、邮箱未查询该用户【{}】", username); + throw new UsernameNotFoundException("用户名或密码错误"); + } + Optional detail = userDetailRepository.findByUserId(user.getId()); + return getUserDetails(enabled, accountNonLocked, authorities, user, + detail.orElse(new UserDetailEntity())); + } + + public static UserDetails getUserDetails(boolean enabled, boolean accountNonLocked, + Collection authorities, + UserEntity user, UserDetailEntity userDetail) { + //TODO 密码是否过期 + + //TODO 状态 + if (!ObjectUtils.isEmpty(user.getStatus())) { + //锁定 + if (user.getStatus().equals(UserStatus.LOCKED) + || user.getStatus().equals(UserStatus.PASS_WORD_EXPIRED_LOCKED) + || user.getStatus().equals(UserStatus.EXPIRED_LOCKED)) { + logger.info("用户【{}】被锁定", user.getUsername()); + accountNonLocked = false; + } + //禁用 + if (user.getStatus().equals(UserStatus.DISABLE)) { + logger.info("用户【{}】被禁用", user.getUsername()); + enabled = false; + } + //根据用户类型封装权限 + SimpleGrantedAuthority authority = new SimpleGrantedAuthority(Roles.USER); + authorities.add(authority); + + //封装 + return new UserDetails(String.valueOf(user.getId()), user.getUsername(), + user.getPassword(), UserType.USER, enabled, true, true, accountNonLocked, + authorities); + } + logger.info("用户【{}】状态异常", user.getUsername()); + throw new AccountExpiredException("用户状态异常"); + } + + /** + * UserRepository + */ + private final UserRepository userRepository; + /** + * UserDetail + */ + private final UserDetailRepository userDetailRepository; + + public UserDetailsServiceImpl(UserRepository userRepository, + UserDetailRepository userDetailRepository) { + this.userRepository = userRepository; + this.userDetailRepository = userDetailRepository; + } +} diff --git a/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/util/JwtUtil.java b/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/util/JwtUtil.java new file mode 100644 index 00000000..c25e69f2 --- /dev/null +++ b/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/util/JwtUtil.java @@ -0,0 +1,157 @@ +/* + * eiam-protocol-jwt - Employee Identity and Access Management Program + * Copyright © 2020-2022 TopIAM (support@topiam.cn) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package cn.topiam.employee.protocol.jwt.util; + +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.stereotype.Component; + +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; +import static cn.topiam.employee.protocol.jwt.constant.ProtocolConstants.*; + +@Component +public class JwtUtil { + // 加密密钥 + @Value("${jwt.secret}") + private static String secret; + // 期限时间 + @Value("${jwt.expiration}") + private static Long expiration; + + public JwtUtil() { + } + + /** + * 根据用户信息生成Token + * @param userDetails + * @return + */ + public static String createToken(UserDetails userDetails) { + Map claims = new HashMap<>(); + claims.put(CLAIM_KEY_USERNAME, userDetails.getUsername()); + claims.put(CLAIM_KEY_LOGINTIME, new Date()); + claims.put(CLAIM_KEY_CREATED, new Date()); + return generateToken(claims); + } + + /** + * 根据 Token 获取用户名 + * @param token + * @return + */ + public static String getUserNameFromToken(String token) { + String username; + try { + Claims claims = getClaimsFormToken(token); + username = claims.getSubject(); + } catch (Exception e) { + username = null; + } + return username; + } + + /** + * 从token中获取载荷 + * @param token + * @return + */ + private static Claims getClaimsFormToken(String token) { + Claims claims = null; + try { + claims = Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody(); + } catch (Exception e) { + e.printStackTrace(); + } + return claims; + } + + /** + * 验证token是否有效 + * @param token + * @param userDetails + * @return + */ + public static boolean validateToken(String token, UserDetails userDetails) { + String username = getUserNameFromToken(token); + return username.equals(userDetails.getUsername()) && !isTokenExpired(token); + } + + /** + * 判断token是否可以被刷新 + * @param token + * @return + */ + public static boolean canRefresh(String token) { + return !isTokenExpired(token); + } + + /** + * 刷新token + * @param token + * @return + */ + public static String refreshToken(String token) { + Claims claims = getClaimsFormToken(token); + claims.put(CLAIM_KEY_CREATED, new Date()); + return generateToken(claims); + } + + /** + * 判断token是否有效 + * @param token + * @return + */ + private static boolean isTokenExpired(String token) { + Date expireDate = getExpiredDateFromToken(token); + return expireDate.before(new Date()); + } + + /** + * 从token中获取过期时间 + * @param token + * @return + */ + private static Date getExpiredDateFromToken(String token) { + Claims claims = getClaimsFormToken(token); + return claims.getExpiration(); + } + + /** + * 生成JWT + * @param claims + * @return + */ + public static String generateToken(Map claims) { + return Jwts.builder().setClaims(claims).setExpiration(generteExpirationDate()) + .signWith(SIGNATURE_ALGORITHM, secret).compact(); + } + + /** + * 生成Token失效时间 + * expiration : 一天的秒数 + * @return + */ + private static Date generteExpirationDate() { + return new Date(System.currentTimeMillis() + expiration * 1000); + } +} -- Gitee From 366d4b0babcc2a0708a1d3cfa48fb1b6b8b59719 Mon Sep 17 00:00:00 2001 From: fanxingmeng Date: Sun, 29 Jan 2023 12:09:01 +0800 Subject: [PATCH 2/5] =?UTF-8?q?pom=E6=96=87=E4=BB=B6=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/pom.xml b/pom.xml index 6b7492d4..044eb636 100644 --- a/pom.xml +++ b/pom.xml @@ -95,6 +95,9 @@ 1.10.0 8.13.2 0.4.0 + + 0.9.1 + 3.4.0 1.1.3 2.21.0 @@ -538,6 +541,17 @@ opensaml-soap-impl ${opensaml.version} + + + io.jsonwebtoken + jjwt + ${jjwt.version} + + + com.auth0 + java-jwt + ${java-jwt.version} + -- Gitee From 6ad5b15b3e442a5aaf9ca459dd188ef220491039 Mon Sep 17 00:00:00 2001 From: fanxingmeng Date: Sun, 29 Jan 2023 12:09:53 +0800 Subject: [PATCH 3/5] =?UTF-8?q?json=E5=B7=A5=E5=85=B7=E7=B1=BB=E4=BF=AE?= =?UTF-8?q?=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../protocol/jwt/filter/JwtAccessDeniedHandler.java | 12 ++++-------- .../jwt/filter/JwtAuthenticationEntryPoint.java | 10 ++++------ .../protocol/jwt/filter/JwtLogoutSuccessHandler.java | 8 +++----- .../protocol/jwt/filter/LoginFailureHandler.java | 7 +++---- .../protocol/jwt/filter/LoginSuccessHandler.java | 8 ++++---- .../employee/protocol/jwt/model/JwtResult.java | 9 +++++++++ 6 files changed, 27 insertions(+), 27 deletions(-) diff --git a/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/JwtAccessDeniedHandler.java b/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/JwtAccessDeniedHandler.java index d0d9a687..b340e51d 100644 --- a/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/JwtAccessDeniedHandler.java +++ b/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/JwtAccessDeniedHandler.java @@ -23,11 +23,13 @@ import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import cn.topiam.employee.support.util.HttpResponseUtils; +import org.springframework.http.HttpStatus; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.web.access.AccessDeniedHandler; import org.springframework.stereotype.Component; -import cn.hutool.json.JSONUtil; + import cn.topiam.employee.protocol.jwt.model.JwtResult; @Component @@ -43,14 +45,8 @@ public class JwtAccessDeniedHandler implements AccessDeniedHandler { response.setContentType("application/json;charset=UTF-8"); response.setStatus(HttpServletResponse.SC_FORBIDDEN); - ServletOutputStream outputStream = response.getOutputStream(); - JwtResult result = JwtResult.fail(accessDeniedException.getMessage()); - outputStream.write(JSONUtil.toJsonStr(result).getBytes("UTF-8")); - - outputStream.flush(); - outputStream.close(); - + HttpResponseUtils.flushResponseJson(response, HttpStatus.BAD_REQUEST.value(),result); } } diff --git a/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/JwtAuthenticationEntryPoint.java b/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/JwtAuthenticationEntryPoint.java index 9c94ba96..72b100e8 100644 --- a/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/JwtAuthenticationEntryPoint.java +++ b/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/JwtAuthenticationEntryPoint.java @@ -24,11 +24,13 @@ import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import cn.topiam.employee.support.util.HttpResponseUtils; +import org.springframework.http.HttpStatus; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.stereotype.Component; -import cn.hutool.json.JSONUtil; + import cn.topiam.employee.protocol.jwt.model.JwtResult; @Component @@ -44,13 +46,9 @@ public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint { response.setContentType("application/json;charset=UTF-8"); response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); - ServletOutputStream outputStream = response.getOutputStream(); JwtResult result = JwtResult.fail("请先登录"); - outputStream.write(JSONUtil.toJsonStr(result).getBytes("UTF-8")); - - outputStream.flush(); - outputStream.close(); + HttpResponseUtils.flushResponseJson(response, HttpStatus.BAD_REQUEST.value(),result); } } diff --git a/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/JwtLogoutSuccessHandler.java b/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/JwtLogoutSuccessHandler.java index 3de8327f..9b7c86a0 100644 --- a/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/JwtLogoutSuccessHandler.java +++ b/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/JwtLogoutSuccessHandler.java @@ -24,6 +24,8 @@ import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import cn.topiam.employee.support.util.HttpResponseUtils; +import org.springframework.http.HttpStatus; import org.springframework.security.core.Authentication; import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler; @@ -46,15 +48,11 @@ public class JwtLogoutSuccessHandler implements LogoutSuccessHandler { } response.setContentType("application/json;charset=UTF-8"); - ServletOutputStream outputStream = response.getOutputStream(); response.setHeader(ProtocolConstants.REQUEST_HEADER, ""); JwtResult result = JwtResult.succ(""); - outputStream.write(JSONUtil.toJsonStr(result).getBytes("UTF-8")); - - outputStream.flush(); - outputStream.close(); + HttpResponseUtils.flushResponseJson(response, HttpStatus.OK.value(),result); } } diff --git a/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/LoginFailureHandler.java b/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/LoginFailureHandler.java index 296e2c1c..8ede15f4 100644 --- a/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/LoginFailureHandler.java +++ b/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/LoginFailureHandler.java @@ -24,6 +24,8 @@ import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import cn.topiam.employee.support.util.HttpResponseUtils; +import org.springframework.http.HttpStatus; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.authentication.AuthenticationFailureHandler; @@ -40,13 +42,10 @@ public class LoginFailureHandler implements AuthenticationFailureHandler { AuthenticationException exception) throws IOException, ServletException { response.setContentType("application/json;charset=UTF-8"); - ServletOutputStream outputStream = response.getOutputStream(); JwtResult result = JwtResult.fail("用户名或密码错误"); - outputStream.write(JSONUtil.toJsonStr(result).getBytes("UTF-8")); + HttpResponseUtils.flushResponseJson(response, HttpStatus.BAD_REQUEST.value(),result); - outputStream.flush(); - outputStream.close(); } } diff --git a/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/LoginSuccessHandler.java b/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/LoginSuccessHandler.java index 5d63a732..e7f7065a 100644 --- a/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/LoginSuccessHandler.java +++ b/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/LoginSuccessHandler.java @@ -25,6 +25,8 @@ import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import cn.topiam.employee.support.util.HttpResponseUtils; +import org.springframework.http.HttpStatus; import org.springframework.security.core.Authentication; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; @@ -47,7 +49,6 @@ public class LoginSuccessHandler implements AuthenticationSuccessHandler { Authentication authentication) throws IOException, ServletException { response.setContentType("application/json;charset=UTF-8"); - ServletOutputStream outputStream = response.getOutputStream(); // 生成jwt返回 String username = authentication.getName(); @@ -56,8 +57,7 @@ public class LoginSuccessHandler implements AuthenticationSuccessHandler { response.setHeader(ProtocolConstants.REQUEST_HEADER, jwt); JwtResult result = JwtResult.succ(""); - outputStream.write(JSONUtil.toJsonStr(result).getBytes("UTF-8")); - outputStream.flush(); - outputStream.close(); + + HttpResponseUtils.flushResponseJson(response, HttpStatus.OK.value(),result); } } diff --git a/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/model/JwtResult.java b/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/model/JwtResult.java index 5714f4eb..1726aa1b 100644 --- a/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/model/JwtResult.java +++ b/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/model/JwtResult.java @@ -24,8 +24,17 @@ import lombok.Data; @Data public class JwtResult implements Serializable { + /** + * 状态码 + */ private int code; + /** + * 内容消息 + */ private String msg; + /** + * 返回内容 + */ private Object data; public static JwtResult succ(Object data) { -- Gitee From f7bf3009a7a98361bcf9efb9ff920814769e042b Mon Sep 17 00:00:00 2001 From: fanxingmeng Date: Sun, 29 Jan 2023 12:11:28 +0800 Subject: [PATCH 4/5] =?UTF-8?q?json=E5=B7=A5=E5=85=B7=E7=B1=BB=E4=BF=AE?= =?UTF-8?q?=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../employee/protocol/jwt/filter/JwtLogoutSuccessHandler.java | 1 - .../topiam/employee/protocol/jwt/filter/LoginFailureHandler.java | 1 - .../topiam/employee/protocol/jwt/filter/LoginSuccessHandler.java | 1 - 3 files changed, 3 deletions(-) diff --git a/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/JwtLogoutSuccessHandler.java b/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/JwtLogoutSuccessHandler.java index 9b7c86a0..443a4531 100644 --- a/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/JwtLogoutSuccessHandler.java +++ b/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/JwtLogoutSuccessHandler.java @@ -31,7 +31,6 @@ import org.springframework.security.web.authentication.logout.LogoutSuccessHandl import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler; import org.springframework.stereotype.Component; -import cn.hutool.json.JSONUtil; import cn.topiam.employee.protocol.jwt.constant.ProtocolConstants; import cn.topiam.employee.protocol.jwt.model.JwtResult; diff --git a/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/LoginFailureHandler.java b/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/LoginFailureHandler.java index 8ede15f4..7a506018 100644 --- a/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/LoginFailureHandler.java +++ b/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/LoginFailureHandler.java @@ -29,7 +29,6 @@ import org.springframework.http.HttpStatus; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.authentication.AuthenticationFailureHandler; -import cn.hutool.json.JSONUtil; import cn.topiam.employee.protocol.jwt.model.JwtResult; /** diff --git a/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/LoginSuccessHandler.java b/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/LoginSuccessHandler.java index e7f7065a..123c8ab0 100644 --- a/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/LoginSuccessHandler.java +++ b/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/filter/LoginSuccessHandler.java @@ -30,7 +30,6 @@ import org.springframework.http.HttpStatus; import org.springframework.security.core.Authentication; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; -import cn.hutool.json.JSONUtil; import cn.topiam.employee.core.security.userdetails.UserDetails; import cn.topiam.employee.protocol.jwt.constant.ProtocolConstants; import cn.topiam.employee.protocol.jwt.model.JwtResult; -- Gitee From 2b2866fd9600afefad2fe9a30aee676e1d1a4909 Mon Sep 17 00:00:00 2001 From: fanxingmeng Date: Tue, 14 Feb 2023 21:46:27 +0800 Subject: [PATCH 5/5] =?UTF-8?q?=E5=AE=89=E5=85=A8=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../protocol/jwt/config/CronConfig.java | 25 +++++++++++++++++ .../protocol/jwt/config/SecurityConfig.java | 27 +++++++++++++++---- .../src/main/resources/application.yml | 22 +++++++++++++++ 3 files changed, 69 insertions(+), 5 deletions(-) create mode 100644 eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/config/CronConfig.java create mode 100644 eiam-protocol/eiam-protocol-jwt/src/main/resources/application.yml diff --git a/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/config/CronConfig.java b/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/config/CronConfig.java new file mode 100644 index 00000000..44cd3de0 --- /dev/null +++ b/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/config/CronConfig.java @@ -0,0 +1,25 @@ +package cn.topiam.employee.protocol.jwt.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import org.springframework.web.filter.CorsFilter; + +@Configuration +public class CronConfig { + private CorsConfiguration build(){ + CorsConfiguration config=new CorsConfiguration(); + config.addAllowedMethod("*"); + config.addAllowedHeader("*"); + config.addAllowedOrigin("*"); + config.setAllowCredentials(true); + return config; + } + @Bean + public CorsFilter corsFilter(){ + UrlBasedCorsConfigurationSource source=new UrlBasedCorsConfigurationSource(); + source.registerCorsConfiguration("/**",build()); + return new CorsFilter(source); + } +} diff --git a/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/config/SecurityConfig.java b/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/config/SecurityConfig.java index 1a4c1234..89f15d3b 100644 --- a/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/config/SecurityConfig.java +++ b/eiam-protocol/eiam-protocol-jwt/src/main/java/cn/topiam/employee/protocol/jwt/config/SecurityConfig.java @@ -19,6 +19,7 @@ package cn.topiam.employee.protocol.jwt.config; import javax.annotation.Resource; +import cn.topiam.employee.protocol.jwt.filter.*; import org.springframework.context.annotation.Bean; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; @@ -29,10 +30,6 @@ import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; -import cn.topiam.employee.protocol.jwt.filter.JwtAccessDeniedHandler; -import cn.topiam.employee.protocol.jwt.filter.JwtAuthenticationEntryPoint; -import cn.topiam.employee.protocol.jwt.filter.JwtAuthenticationFilter; -import cn.topiam.employee.protocol.jwt.filter.LoginSuccessHandler; import cn.topiam.employee.protocol.jwt.userdetails.UserDetailsServiceImpl; @EnableWebSecurity @@ -41,6 +38,19 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { @Resource private UserDetailsServiceImpl userDetailsService; + @Resource + private JwtAuthenticationEntryPoint authenticationEntryPoint; + + @Resource + private LoginFailureHandler loginFailureHandler; + + @Resource + private LoginSuccessHandler loginSuccessHandler; + + @Resource + private JwtLogoutSuccessHandler jwtLogoutSuccessHandler; + + @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() @@ -53,7 +63,14 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { .sessionCreationPolicy(SessionCreationPolicy.STATELESS) //禁用session // 异常处理器 .and().exceptionHandling().authenticationEntryPoint(new JwtAuthenticationEntryPoint()) - .accessDeniedHandler(new JwtAccessDeniedHandler()); + .accessDeniedHandler(new JwtAccessDeniedHandler()) + //登录设置 + .and().formLogin().permitAll() + .successHandler(loginSuccessHandler) + .failureHandler(loginFailureHandler) + .and().logout().permitAll() + .logoutSuccessHandler(jwtLogoutSuccessHandler) + .deleteCookies("JSESSIONID"); } @Override diff --git a/eiam-protocol/eiam-protocol-jwt/src/main/resources/application.yml b/eiam-protocol/eiam-protocol-jwt/src/main/resources/application.yml new file mode 100644 index 00000000..a377119e --- /dev/null +++ b/eiam-protocol/eiam-protocol-jwt/src/main/resources/application.yml @@ -0,0 +1,22 @@ +# +# eiam-protocol-jwt - Employee Identity and Access Management Program +# Copyright © 2020-2022 TopIAM (support@topiam.cn) +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# + + +jwt: + secret: dhdsoasdsajkhfahhkfhjlj + expiration: 604800 \ No newline at end of file -- Gitee