马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
1.Security 先容
- 官网链接:https://docs.spring.io/spring-security/reference/5.7.6/servlet/architecture.html
依靠导入
- <parent>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-parent</artifactId>
- <version>2.7.8</version>
- <relativePath/> <!-- lookup parent from repository -->
- </parent>
- <dependencys>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-security</artifactId>
- </dependency>
- </dependencys>
复制代码 2.Security 自界说拦截器实现多种登录方式
1. 账户暗码登录
- 1.自定义MyUsernamePasswordFilter
复制代码- /**
- * 2023/2/26
- *
- * @author cyh
- * 10:30
- */
- @Slf4j
- public class MyUsernamePasswordFilter extends AbstractAuthenticationProcessingFilter {
- public static final String SPRING_SECURITY_FORM_USERNAME_KEY = "username";
- public static final String SPRING_SECURITY_FORM_PASSWORD_KEY = "password";
- // 自定拦截路由
- private static final AntPathRequestMatcher DEFAULT_ANT_PATH_REQUEST_MATCHER = new AntPathRequestMatcher("/user/login", "POST");
- private String usernameParameter = SPRING_SECURITY_FORM_USERNAME_KEY;
- private String passwordParameter = SPRING_SECURITY_FORM_PASSWORD_KEY;
- private boolean postOnly = true;
- private FormUser user;
- public MyUsernamePasswordFilter() {
- super(DEFAULT_ANT_PATH_REQUEST_MATCHER);
- }
- public MyUsernamePasswordFilter(AuthenticationManager authenticationManager) {
- super(DEFAULT_ANT_PATH_REQUEST_MATCHER, authenticationManager);
- }
- public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
- if (this.postOnly && !request.getMethod().equals("POST")) {
- throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
- } else {
- log.info("url:" + request.getRequestURI());
- // 获取登录表单
- getUser(request);
- String username = obtainUsername();
- username = username != null ? username.trim() : "";
- String password = obtainPassword();
- password = password != null ? password : "";
- MyUsernamePasswordToken authRequest = MyUsernamePasswordToken.unauthenticated(username, password);
- this.setDetails(request, authRequest);
- this.setContinueChainBeforeSuccessfulAuthentication(false);
- return this.getAuthenticationManager().authenticate(authRequest);
- }
- }
- @Nullable
- protected String obtainPassword() {
- return user.getPassword();
- }
- @Nullable
- protected String obtainUsername() {
- return user.getUsername();
- }
- protected void setDetails(HttpServletRequest request, MyUsernamePasswordToken authRequest) {
- authRequest.setDetails(this.authenticationDetailsSource.buildDetails(request));
- }
- public void setUsernameParameter(String usernameParameter) {
- Assert.hasText(usernameParameter, "Username parameter must not be empty or null");
- this.usernameParameter = usernameParameter;
- }
- public void setPasswordParameter(String passwordParameter) {
- Assert.hasText(passwordParameter, "Password parameter must not be empty or null");
- this.passwordParameter = passwordParameter;
- }
- public void setPostOnly(boolean postOnly) {
- this.postOnly = postOnly;
- }
- public final String getUsernameParameter() {
- return this.usernameParameter;
- }
- public final String getPasswordParameter() {
- return this.passwordParameter;
- }
- /**
- * 获取登录用户信息
- *
- * @param request
- * @return
- */
- private void getUser(HttpServletRequest request) {
- ObjectMapper objectMapper = new ObjectMapper();
- objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
- try {
- user = objectMapper.readValue(request.getInputStream(), FormUser.class);
- log.info("user:" + user.toString());
- } catch (Exception e) {
- throw new NullPointerException("获取不到登录信息");
- }
- }
- }
复制代码- @Slf4j
- public class MyUsernamePasswordProvider implements AuthenticationProvider, InitializingBean, MessageSourceAware {
- private final MyUserDetailsService userDetailsService;
- private final PasswordEncoder passwordEncoder;
- private MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
- public MyUsernamePasswordProvider(MyUserDetailsService userDetailsService, PasswordEncoder passwordEncoder) {
- this.userDetailsService = userDetailsService;
- this.passwordEncoder = passwordEncoder;
- }
- @Override
- public Authentication authenticate(Authentication authentication) throws AuthenticationException {
- try {
- MyUsernamePasswordToken tokenReq = (MyUsernamePasswordToken) authentication;
- String username = tokenReq.getPrincipal().toString();
- String password = tokenReq.getCredentials().toString();
- LoginUser loginUser = (LoginUser) userDetailsService.loadUserByUsername(username);
- if (!passwordEncoder.matches(password, loginUser.getPassword())) {
- throw new RuntimeException("账号或者密码错误");
- }
- // 将权限列表加入MyUsernamePasswordToken
- MyUsernamePasswordToken myUsernameAuthenticationToken = MyUsernamePasswordToken.authenticated(loginUser, null, null);
- myUsernameAuthenticationToken.setDetails(authentication.getDetails());
- return myUsernameAuthenticationToken;
- } catch (Exception e) {
- e.printStackTrace();
- throw new BadCredentialsException(e.getMessage());
- }
- }
- @Override
- public boolean supports(Class<?> authentication) {
- return (MyUsernamePasswordToken.class.isAssignableFrom(authentication));
- }
- @Override
- public void afterPropertiesSet() throws Exception {
- Assert.notNull(userDetailsService, "userDetailsService must not be null");
- Assert.notNull(userDetailsService, "userDetailsService must not be null");
- }
- @Override
- public void setMessageSource(MessageSource messageSource) {
- this.messages = new MessageSourceAccessor(messageSource);
- }
复制代码- public class MyUsernamePasswordToken extends AbstractAuthenticationToken {
- private static final long serialVersionUID = 570L;
- private final Object principal;
- private Object credentials;
- public MyUsernamePasswordToken(Object principal, Object credentials) {
- super((Collection) null);
- this.principal = principal;
- this.credentials = credentials;
- this.setAuthenticated(false);
- }
- public MyUsernamePasswordToken(Object principal, Object credentials, Collection<? extends GrantedAuthority> authorities) {
- super(authorities);
- this.principal = principal;
- this.credentials = credentials;
- super.setAuthenticated(true);
- }
- public static MyUsernamePasswordToken unauthenticated(Object principal, Object credentials) {
- return new MyUsernamePasswordToken(principal, credentials);
- }
- public static MyUsernamePasswordToken authenticated(Object principal, Object credentials, Collection<? extends GrantedAuthority> authorities) {
- return new MyUsernamePasswordToken(principal, credentials, authorities);
- }
- public Object getCredentials() {
- return this.credentials;
- }
- public Object getPrincipal() {
- return this.principal;
- }
- public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
- Assert.isTrue(!isAuthenticated, "Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead");
- super.setAuthenticated(false);
- }
- public void eraseCredentials() {
- super.eraseCredentials();
- this.credentials = null;
- }
- }
复制代码- @Data
- @AllArgsConstructor
- @NoArgsConstructor
- public class LoginUser implements UserDetails, Serializable {
- private static final long serialVersionUID = -53711580203962796L;
- private User user;https://www.yuque.com/u37030796/eb88se/uekda8twfz1pdq50#db5c42be
- private List<Long> permissions;
- public LoginUser(User user, List<Long> permissions) {
- this.user = user;
- this.permissions = permissions;
- }
- private List<SimpleGrantedAuthority> authorities;
- @Override
- public Collection<? extends GrantedAuthority> getAuthorities() {
- if (authorities != null) {
- return authorities;
- }
- if (CollUtil.isEmpty(permissions)) {
- return null;
- }
- authorities = permissions.stream().filter(x -> !ObjectUtil.isNull(x)).map(x -> x.toString())
- .map(SimpleGrantedAuthority::new)
- .collect(Collectors.toList());
- return authorities;
- }
- @Override
- public String getPassword() {
- return user.getPassword();
- }
- @Override
- public String getUsername() {
- return user.getUsername();
- }
- @Override
- public boolean isAccountNonExpired() {
- return true;
- }
- @Override
- public boolean isAccountNonLocked() {
- return true;
- }
- @Override
- public boolean isCredentialsNonExpired() {
- return true;
- }
- @Override
- public boolean isEnabled() {
- return true;
- }
- }
复制代码- @Slf4j
- @Service
- public class MyUserDetailsService implements UserDetailsService {
- @Autowired
- UserMapper userMapper;
- @Override
- public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
- log.info("userDetails");
- LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
- wrapper.eq(User::getUsername, username);
- User user = userMapper.selectOne(wrapper);
- if (Objects.isNull(user)) {
- throw new UserNotFindException("找不到用户");
- }
- if (user.getStatus() == 1) {
- throw new UserNotFindException("账户已经被禁用");
- }
- return new LoginUser(user, null);
- }
- }
复制代码- /**
- * 2023/2/26
- *
- * @author cyh
- * 15:04
- */
- @Slf4j
- @Component
- public class MyUsernamePasswordSuccessHandler implements AuthenticationSuccessHandler {
- @Autowired
- RedisTemplate<String, String> redisTemplate;
- @Autowired
- UserRoleService userRoleService;
- @Autowired
- IUserService userService;
- @Override
- public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authentication) throws IOException, ServletException {
- chain.doFilter(request, response);
- }
- @Override
- public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
- response.setCharacterEncoding("utf-8");
- response.setContentType("application/json;charset=utf-8");
- LoginUser loginUser = (LoginUser) authentication.getPrincipal();
- Long uid = loginUser.getUser().getId();
- // 每次登录添加登录ip和时间
- // 获取权限列表并返回
- User user = loginUser.getUser();
- user.setLastLoginTime(LocalDateTime.now().toString());
- user.setLoginIp(ServletUtil.getClientIP(request));
- userService.updateById(user);
- String token = MyJwtUtil.getToken(uid, RequestKey.ADMIN_USER.getKey());
- redisTemplate.opsForValue().set(RequestKey.ADMIN_USER.getKey() + "login:" + uid, token, 60 * 60 * 72, TimeUnit.SECONDS);
- // TODO redis存放门店列表
- // TODO redis存放权限列表
- List<Long> permsByUserId = userRoleService.getPermsByUserId(uid);
- ResultAuthority resultAuthority = new ResultAuthority(token, permsByUserId);
- ResultData<ResultAuthority> ok = ResultData.success("ok", resultAuthority);
- response.getWriter().print(JSONUtil.parseObj(ok));
- log.info("登录成功:" + authentication.getPrincipal().toString());
- }
- }
复制代码- @Slf4j
- public class MyUsernamePasswordErrorHandler implements AuthenticationFailureHandler {
- @Override
- public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
- log.info(exception.getMessage());
- response.setCharacterEncoding("utf-8");
- response.setContentType("application/json;charset=utf-8");
- response.setStatus(200);
- ResultData<ResultAuthority> ok = ResultData.fail(500, exception.getMessage());
- response.getWriter().print(JSONUtil.parseObj(ok));
- }
- }
复制代码 3. 微信授权登录
- /**
- * 2023/3/6
- *
- * @author cyh
- * 9:29
- */
- @Slf4j
- public class WxLoginFilter extends AbstractAuthenticationProcessingFilter {
- private static final AntPathRequestMatcher DEFAULT_ANT_PATH_REQUEST_MATCHER = new AntPathRequestMatcher("/wxlogin/userinfo", "GET");
- private boolean postOnly = true;
- public WxLoginFilter() {
- super(DEFAULT_ANT_PATH_REQUEST_MATCHER);
- }
- public WxLoginFilter(AuthenticationManager authenticationManager) {
- super(DEFAULT_ANT_PATH_REQUEST_MATCHER, authenticationManager);
- }
- @Override
- public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
- log.info("正在进行拦截");
- if (!request.getMethod().equals("GET")) {
- throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
- } else {
- // 从请求头里获取到code
- String code = obtainCode(request);
- code = code != null ? code.trim() : "";
- WxUserToken wxUserToken = WxUserToken.unauthenticated(code, null);
- this.setDetails(request, wxUserToken);
- return this.getAuthenticationManager().authenticate(wxUserToken);
- }
- }
- protected void setDetails(HttpServletRequest request, WxUserToken authRequest) {
- authRequest.setDetails(this.authenticationDetailsSource.buildDetails(request));
- }
- @Nullable
- protected String obtainCode(HttpServletRequest request) {
- return request.getParameter("code");
- }
- public void setPostOnly(boolean postOnly) {
- this.postOnly = postOnly;
- }
- }
复制代码- /**
- * 2023/3/6
- *
- * @author cyh
- * 9:35
- */
- @Slf4j
- public class WxLoginProvider implements AuthenticationProvider, InitializingBean, MessageSourceAware {
- private final WxLoginServiceImpl wxLoginService;
- private final WxLoginUtilService wxLoginUtilService;
- private MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
- public WxLoginProvider(WxLoginServiceImpl userDetailsService, WxLoginUtilService wxLoginUtilService) {
- this.wxLoginService = userDetailsService;
- this.wxLoginUtilService = wxLoginUtilService;
- }
- @Override
- public Authentication authenticate(Authentication authentication) throws AuthenticationException {
- WxUserToken tokenReq = (WxUserToken) authentication;
- String code = (String) tokenReq.getPrincipal();
- WxUserToken wxUserToken = null;
- String openid = null;
- // 根据code拿到access_token和openid
- try {
- // 向微信获取
- WxOAuth2AccessToken accessToken = wxLoginUtilService.getAccessTokenAndOpenID(code);
- openid = wxLoginUtilService.getWxUserInfo(accessToken);
- } catch (WxErrorException e) {
- throw new RuntimeException(e);
- }
- // 从数据库里获取用户信息并设置认证通过
- WxLoginEntity wxLoginEntity = wxLoginService.loadUserByUsername(openid);
- log.info("userDetails:{}", wxLoginEntity.toString());
- wxUserToken = WxUserToken.authenticated(wxLoginEntity, null, null);
- wxUserToken.setDetails(authentication.getDetails());
- return wxUserToken;
- }
- @Override
- public boolean supports(Class<?> authentication) {
- return (WxUserToken.class.isAssignableFrom(authentication));
- }
- @Override
- public void afterPropertiesSet() throws Exception {
- Assert.notNull(wxLoginService, "userDetailsService must not be null");
- }
- @Override
- public void setMessageSource(MessageSource messageSource) {
- this.messages = new MessageSourceAccessor(messageSource);
- }
- }
复制代码- /**
- * 2023/3/6
- *
- * @author cyh
- * 9:33
- */
- public class WxUserToken extends AbstractAuthenticationToken {
- private static final long serialVersionUID = 570L;
- private final Object principal;
- private Object credentials;
- public WxUserToken(Object principal, Object credentials) {
- super((Collection) null);
- this.principal = principal;
- this.credentials = credentials;
- this.setAuthenticated(false);
- }
- public WxUserToken(Object principal, Object credentials, Collection<? extends GrantedAuthority> authorities) {
- super(authorities);
- this.principal = principal;
- this.credentials = credentials;
- super.setAuthenticated(true);
- }
- public static WxUserToken unauthenticated(Object principal, Object credentials) {
- return new WxUserToken(principal, credentials);
- }
- public static WxUserToken authenticated(Object principal, Object credentials, Collection<? extends GrantedAuthority> authorities) {
- return new WxUserToken(principal, credentials, authorities);
- }
- public Object getCredentials() {
- return this.credentials;
- }
- public Object getPrincipal() {
- return this.principal;
- }
- public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
- Assert.isTrue(!isAuthenticated, "Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead");
- super.setAuthenticated(false);
- }
- public void eraseCredentials() {
- super.eraseCredentials();
- this.credentials = null;
- }
- }
复制代码- /**
- * 2023/3/6
- *
- * @author cyh
- * 14:12
- */
- @Data
- @AllArgsConstructor
- public class WxLoginEntity implements UserDetails {
- private OrderUser user;
- @Override
- public Collection<? extends GrantedAuthority> getAuthorities() {
- return null;
- }
- @Override
- public String getPassword() {
- return null;
- }
- @Override
- public String getUsername() {
- return user.getOpenid();
- }
- @Override
- public boolean isAccountNonExpired() {
- return true;
- }
- @Override
- public boolean isAccountNonLocked() {
- return true;
- }
- @Override
- public boolean isCredentialsNonExpired() {
- return true;
- }
- @Override
- public boolean isEnabled() {
- return true;
- }
- }
复制代码- @Slf4j
- @Service
- public class WxLoginServiceImpl implements UserDetailsService {
- @Autowired
- WxLoginUtilService wxLoginUtilService;
- @Autowired
- IOrderUserService orderUserService;
- @Value("${wxlogin.appid}")
- private String appid;
- /**
- * 获取数据库用户信息
- *
- * @param username
- * @return
- * @throws UsernameNotFoundException
- */
- @Override
- public WxLoginEntity loadUserByUsername(String username) throws UsernameNotFoundException {
- OrderUser orderUser;
- orderUser = orderUserService.getOne(new LambdaQueryWrapper<OrderUser>().eq(OrderUser::getOpenid, username));
- if (ObjectUtil.isNull(orderUser)) {
- throw new UsernameNotFoundException("找不到用户");
- }
- return new WxLoginEntity(orderUser);
- }
- }
复制代码- @Slf4j
- @Component
- public class WxLoginSuccessHandler implements AuthenticationSuccessHandler {
- @Autowired
- RedisTemplate<String, String> redisTemplate;
- private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
- @Override
- @IgnoreResponseAdvice
- public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException {
- // 获取当前认证的用户
- WxLoginEntity loginUser = (WxLoginEntity) authentication.getPrincipal();
- // 获取用户的id
- Long uid = loginUser.getUser().getId();
- // 获取token
- String token = MyJwtUtil.getToken(uid, RequestKey.WX_USER.getKey());
- redisTemplate.opsForValue().set(RequestKey.WX_USER.getKey() + "login:" + loginUser.getUser().getId(), token, 60 * 60 * 72, TimeUnit.SECONDS);
- // 设置返回的id和token
- response.setCharacterEncoding("utf-8");
- response.setContentType("application/json;charset=utf-8");
- Map<String, String> map = new HashMap<>();
- map.put("nickname", loginUser.getUser().getNickname());
- map.put("openid", loginUser.getUser().getOpenid());
- map.put("token", token);
- // 返回给前端
- ResultData<Map> ok = ResultData.success("ok", map);
- response.getWriter().print(JSONUtil.parseObj(ok));
- }
- }
复制代码- /**
- * 2023/3/6
- *
- * @author cyh
- * 9:35
- */
- public class WxLoginErrorHandler implements AuthenticationFailureHandler {
- @Override
- public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
- throw new RuntimeException("授权登录验证失败");
- }
- }
复制代码 自界说token拦截器
- @Slf4j
- public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
- /**
- * 请求头token的key
- */
- private String tokenKey = RequestKey.TOKEN_KEY.getKey();
- /**
- * 用户的value
- */
- private String wxUser = RequestKey.WX_USER.getKey();
- /**
- * 管理用户的value
- */
- private String adminUser = RequestKey.ADMIN_USER.getKey();
- /**
- * redis 工具
- */
- private RedisTemplate<String, String> redisTemplate;
- /**
- * 微信登录用户
- */
- private IOrderUserService orderUserService;
- /**
- * 管理用户
- */
- private IUserService userService;
- /**
- * 用户权限
- */
- private UserRoleService userRoleService;
- public JwtAuthenticationTokenFilter(IOrderUserService orderUserService, IUserService userService, UserRoleService userRoleService, RedisTemplate<String, String> redisTemplate) {
- this.orderUserService = orderUserService;
- this.userService = userService;
- this.userRoleService = userRoleService;
- this.redisTemplate = redisTemplate;
- }
- @Override
- protected void doFilterInternal(HttpServletRequest request,
- HttpServletResponse response,
- FilterChain chain) throws ServletException, IOException {
- String reqToken = request.getHeader(this.tokenKey);
- log.info("现在{}正在进行jwt认证:{}", request.getRequestURI(), reqToken);
- // 判断token和请求用户是否存在
- if (Strings.isBlank(reqToken)) {
- chain.doFilter(request, response);
- return;
- }
- try {
- // 判断token是否过期
- if (!MyJwtUtil.verifyToken(reqToken)) {
- throw new TokenException("非法token, token已过期");
- }
- // 从token上获取uid
- Long uid = MyJwtUtil.getUid(reqToken);
- String reqUser = MyJwtUtil.getRoleUser(reqToken);
- if (ObjectUtil.isNull(uid) || ObjectUtil.isNull(reqUser)) {
- throw new TokenException("非法token.uid获取不到");
- }
- if (StrUtil.equals(reqUser, wxUser)) {
- // 与redis中的用户token对比
- String redisToken = redisTemplate.opsForValue().get(wxUser + "login:" + uid);
- log.info("redisToken:{}", redisToken);
- if (StrUtil.isBlankIfStr(redisToken) || !StrUtil.equals(redisToken, reqToken)) {
- throw new TokenException("非法token,与redis中不一致");
- }
- // 判断获取的用户存不存在
- OrderUser user = orderUserService.getById(uid);
- if (ObjectUtil.isNull(user)) {
- throw new TokenException("非法token,登录用户类别获取不到");
- }
- // 存在设置认证通过
- WxLoginEntity wxLoginEntity = new WxLoginEntity(user);
- WxUserToken wxUserToken = WxUserToken.authenticated(wxLoginEntity, null, null);
- SecurityContextHolder.getContext().setAuthentication(wxUserToken);
- chain.doFilter(request, response);
- return;
- }
- if (StrUtil.equals(reqUser, adminUser)) {
- // 与redis中的用户token对比
- String redisToken = redisTemplate.opsForValue().get(adminUser + "login:" + uid);
- log.info("redisToken:{}", redisToken);
- if (StrUtil.isBlankIfStr(redisToken) || !StrUtil.equals(redisToken, reqToken)) {
- throw new TokenException("非法token,与redis中不一致");
- }
- // TODO 从redis获取用户信息
- User byId = userService.getById(uid);
- // TODO 将用户信息放入MyUsernamePasswordToken
- List<Long> permsByUserId = userRoleService.getPermsByUserId(uid);
- LoginUser loginUser = new LoginUser(byId, permsByUserId);
- if (loginUser.getUser().getStatus() == 1) {
- redisTemplate.delete(adminUser + "login:" + uid);
- throw new TokenException("账户被禁用,请重新登录");
- }
- MyUsernamePasswordToken myUsernamePasswordToken = new MyUsernamePasswordToken(loginUser, null,
- loginUser.getAuthorities());
- // TODO 将认证的信息放入 SecurityContextHolder.getContext()
- SecurityContextHolder.getContext().setAuthentication(myUsernamePasswordToken);
- chain.doFilter(request, response);
- return;
- }
- throw new TokenException("非法token");
- } catch (TokenException exception) {
- JwtUnAuthorizedResponseAuthenticationEntryPoint point = new JwtUnAuthorizedResponseAuthenticationEntryPoint();
- point.commence(request, response, exception);
- }
- }
- }
复制代码 4. Security设置类
- @Configuration
- @EnableWebSecurity // 添加 security 过滤器\
- @EnableGlobalMethodSecurity(prePostEnabled = true)
- public class SecurityConfig {
- /**
- * token认证器
- */
- @Autowired
- IOrderUserService orderUserService;
- @Autowired
- IUserService userService;
- @Autowired
- MyJwtUtil myJwtUtil;
- @Autowired
- UserRoleService userRoleService;
- @Autowired
- RedisTemplate<String, String> redisTemplate;
- JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter() {
- return new JwtAuthenticationTokenFilter(orderUserService, userService, myJwtUtil, userRoleService, redisTemplate);
- }
- /**
- * 放行路径配置类
- */
- @Autowired
- SecurityRelease securityRelease;
- /**
- * 放行路径
- */
- @Bean
- public PasswordEncoder passwordEncoder() {
- return new BCryptPasswordEncoder();
- }
- /**
- * 获取AuthenticationManager(认证管理器),登录时认证使用
- *
- * @return
- * @throws Exception
- */
- @Bean
- public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
- AuthenticationManager authenticationManager = authenticationConfiguration.getAuthenticationManager();
- return authenticationManager;
- }
- @Bean
- SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
- http.exceptionHandling().accessDeniedHandler(new AccessDeniedHandlerImpl());
- return
- http.authorizeRequests(authorize -> authorize
- .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
- // 请求放开
- .antMatchers(securityRelease.getReleaseUrl()).permitAll()
- // 其他地址的访问均需验证权限
- .anyRequest().authenticated()
- ) // 基于 token,不需要 csrf
- .csrf().disable()
- .formLogin().disable()
- // 基于 token,不需要 session
- .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
- .addFilterAt(wxLoginFilter(), UsernamePasswordAuthenticationFilter.class)
- .addFilterAt(usernamePasswordFilter(), UsernamePasswordAuthenticationFilter.class)
- .addFilterBefore(jwtAuthenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class)
- .build();
- }
- /**
- * 配置跨源访问(CORS)
- *
- * @return
- */
- @Bean
- CorsConfigurationSource corsConfigurationSource() {
- UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
- source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues());
- return source;
- }
- @Autowired
- WxLoginServiceImpl wxLoginService;
- @Autowired
- WxLoginUtilService wxLoginUtilService;
- @Autowired
- WxLoginSuccessHandler wxLoginSuccessHandler;
- // 添加微信用户登录拦截器
- WxLoginFilter wxLoginFilter() throws Exception {
- WxLoginFilter myUsernameFilter = new WxLoginFilter();
- ProviderManager providerManager = new ProviderManager(Collections.singletonList(wxLoginProvider()));
- myUsernameFilter.setAuthenticationManager(providerManager);
- myUsernameFilter.setAuthenticationSuccessHandler(wxLoginSuccessHandler);
- myUsernameFilter.setAuthenticationFailureHandler(new WxLoginErrorHandler());
- myUsernameFilter.setContinueChainBeforeSuccessfulAuthentication(true);
- return myUsernameFilter;
- }
- WxLoginProvider wxLoginProvider() {
- WxLoginProvider provider = new WxLoginProvider(wxLoginService, wxLoginUtilService);
- return provider;
- }
- @Autowired
- MyUsernamePasswordSuccessHandler myUsernamePasswordSuccessHandler;
- @Autowired
- MyUserDetailsService userDetailsService;
- /**
- * 添加用户登录拦截器
- *
- * @return
- */
- MyUsernamePasswordFilter usernamePasswordFilter() {
- MyUsernamePasswordFilter filter = new MyUsernamePasswordFilter();
- ProviderManager manager = new ProviderManager(Collections.singletonList(usernamePasswordProvider()));
- filter.setAuthenticationManager(manager);
- filter.setAuthenticationFailureHandler(new MyUsernamePasswordErrorHandler());
- filter.setAuthenticationSuccessHandler(myUsernamePasswordSuccessHandler);
- return filter;
- }
- MyUsernamePasswordProvider usernamePasswordProvider() {
- return new MyUsernamePasswordProvider(userDetailsService, passwordEncoder());
- }
- }
复制代码 4.yml 文件设置放行路径
- my-security:
- releaseUrl:
- - /wxlogin/**
- - /user/login
- - /user/logout
- - /doc.html
- - /webjars/**
- - /swagger-resources/**
- - /v2/**
- - /wx-pay/**
- - /**
复制代码 5. 放行路径设置类
- /**
- * 2023/3/13
- * security 放行路径配置类
- *
- * @author cyh
- * 14:27
- */
- @Configuration
- @Data
- @ConfigurationProperties(prefix = "my-security")
- public class SecurityRelease {
- private String[] releaseUrl;
- }
复制代码 |