《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》,点击传送门,即可获取!
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
/**
- 资源服务配置
*/
@Configuration
@EnableResourceServer
public class AuthResourceServerConfig extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated();
}
}
JwtTokenStoreConfig
package com.b8.auth.config;
import com.b8.auth.enhancer.B8AuthTokenEnhancer;
import com.b8.auth.properties.JwtCAProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.security.rsa.crypto.KeyStoreKeyFactory;
import java.security.KeyPair;
@Configuration
@EnableConfigurationProperties(value = JwtCAProperties.class)
public class JwtTokenStoreConfig {
@Bean
public TokenStore jwtTokenStore(){
return new JwtTokenStore(jwtAccessTokenConverter());
}
@Bean
public B8AuthTokenEnhancer b8AuthTokenEnhancer() {
return new B8AuthTokenEnhancer();
}
@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter(){
JwtAccessTokenConverter accessTokenConverter = new
JwtAccessTokenConverter();
//配置JWT使用的秘钥 非对称加密
accessTokenConverter.setKeyPair(keyPair());
return accessTokenConverter;
}
@Autowired
private JwtCAProperties jwtCAProperties;
@Bean
public KeyPair keyPair() {
KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(new ClassPathResource(jwtCAProperties.getKeyPairName()), jwtCAProperties.getKeyPairSecret().toCharArray());
return keyStoreKeyFactory.getKeyPair(jwtCAProperties.getKeyPairAlias(), jwtCAProperties.getKeyPairStoreSecret().toCharArray());
}
}
RedisConfig
package com.b8.auth.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;
/**
- @author zhiwei Liao
*/
@Configuration
public class RedisConfig {
@Autowired
private RedisConnectionFactory redisConnectionFactory;
@Bean
public TokenStore tokenStore(){
// access_token
return new RedisTokenStore(redisConnectionFactory);
}
}
WebSecurityConfig
package com.b8.auth.config;
import com.b8.auth.service.B8AuthUserDetailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
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.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
/**
-
@Description 配置SpringSecurity,“将Spring Security与Spring Gateway一起使用时出现无法访问javax.servlet.Filter”错误”,
-
把Spring Gateway和Spring Security放在一起,因为我想保护我的网关。但是在实现了以下扩展WebSecurityConfigurerAdapter的类之后,
-
项目抛出java:无法访问javax.servlet.Filter
-
从Spring Cloud Gateway文档中:Spring Cloud Gateway需要Spring Boot和Spring Webflux提供的Netty运行时。
-
它不能在传统的Servlet容器中工作,也不能在构建为WAR时工作。扩展WebSecurityConfigurerAdapter是为了基于servlet的应用程序
-
@Author zhiwei Liao
-
@Date 2021/8/17 15:44
**/
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private B8AuthUserDetailService userDetailService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailService);
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
/**
-
@Description 密码模式
-
@MethodReturnType org.springframework.security.crypto.password.PasswordEncoder
-
@Author zhiwei Liao
-
@Date 2021/8/17 15:46
**/
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin().permitAll()
.and().authorizeRequests()
.antMatchers(“/oauth/**”).permitAll()//不拦截
.anyRequest()
.authenticated()
.and().logout().permitAll()//退出放行
.and().csrf().disable();
}
}
UserinfoDetails
package com.b8.auth.domain;
import com.common.entity.po.B8UserUserinfoEntity;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Arrays;
import java.util.Collection;
/**
- @author zhiwei Liao
*/
public class UserinfoDetails implements UserDetails {
private B8UserUserinfoEntity userUserinfo;
public UserinfoDetails(B8UserUserinfoEntity userUserinfo) {
this.userUserinfo = userUserinfo;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
//返回当前用户的权限 BRAC user role authority
return Arrays.asList(new SimpleGrantedAuthority(“TEST”));
}
// 获取用户密码(凭证)
@Override
public String getPassword() {
return userUserinfo.getCredential();
}
// 获取用户名
@Override
public String getUsername() {
return userUserinfo.getNickNameId();
}
// 判断帐号是否已经过期
@Override
public boolean isAccountNonExpired() {
return true;
}
// 判断帐号是否已被锁定
@Override
public boolean isAccountNonLocked() {
return true;
}
// 判断用户凭证是否已经过期
@Override
public boolean isCredentialsNonExpired() {
return true;
}
// 判断用户帐号是否已启用
@Override
public boolean isEnabled() {
return !userUserinfo.getUserStatus().equals(“FREEZE”);
}
public B8UserUserinfoEntity getUserUserinfo() {
return userUserinfo;
}
}
B8AuthTokenEnhancer
package com.b8.auth.enhancer;
import com.b8.auth.domain.UserinfoDetails;
import com.common.entity.po.B8UserUserinfoEntity;
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
import java.util.HashMap;
import java.util.Map;
public class B8AuthTokenEnhancer implements TokenEnhancer {
@Override
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
UserinfoDetails userinfoDetails = (UserinfoDetails) authentication.getPrincipal();
final Map<String, Object> additionalInfo = new HashMap<>();
final Map<String, Object> retMap = new HashMap<>();
//todo 这里暴露userId到Jwt的令牌中,后期可以根据自己的业务需要 进行添加字段
additionalInfo.put(“userId”,userinfoDetails.getUserUserinfo().getId());
additionalInfo.put(“userName”,userinfoDetails.getUserUserinfo().getNickNameId());
additionalInfo.put(“nickName”,userinfoDetails.getUserUserinfo().getDisplayName());
additionalInfo.put(“loginType”,userinfoDetails.getUserUserinfo().getLoginType());
retMap.put(“additionalInfo”,additionalInfo);
((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(retMap);
return accessToken;
}
}
JwtCAProperties
package com.b8.auth.properties;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
-
@Description 读取配置文件中的属性配置
-
@Author zhiwei Liao
-
@Date 2021/8/18 10:04
**/
@Data
@ConfigurationProperties(prefix = “b8auth.jwt”)
public class JwtCAProperties {
/**
- 证书名称
*/
private String keyPairName;
/**
- 证书别名
*/
private String keyPairAlias;
/**
- 证书私钥
*/
private String keyPairSecret;
/**
- 证书存储密钥
*/
private String keyPairStoreSecret;
}
UserServiceHystrix
package com.b8.auth.service.impl;
import com.b8.auth.api.ResultData;
import com.b8.auth.service.UserInfoFeignService;
import com.common.entity.po.B8UserUserinfoEntity;
import org.springframework.stereotype.Component;
/**
-
@author zhiwei Liao
-
@version 1.0
-
@Description
-
@Date 2021/8/17 15:25
*/
@Component
public class UserServiceHystrix implements UserInfoFeignService {
@Override
public ResultData getUserinfoById(String userId) {
return null;
}
@Override
public ResultData getUserByUsername(String username) {
return null;
}
}
B8AuthUserDetailService
package com.b8.auth.service;
import com.b8.auth.api.ResultData;
import com.b8.auth.domain.UserinfoDetails;
import com.common.entity.po.B8UserUserinfoEntity;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
/**
-
@author zhiwei Liao
-
@version 1.0
-
@Description
-
@Date 2021/8/17 15:02
*/
@Service
@Slf4j
public class B8AuthUserDetailService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// TODO 查数据库获取用户信息 rpc调用
// 加载用户信息
if (StringUtils.isEmpty(username)) {
log.warn(“用户登陆用户名为空:{}”, username);
throw new UsernameNotFoundException(“用户名不能为空”);
}
B8UserUserinfoEntity userUserinfo = getByUsername(username);
if (null == userUserinfo) {
log.warn(“根据用户名没有查询到对应的用户信息:{}”, username);
}
log.info(“根据用户名:{}获取用户登陆信息:{}”, username, userUserinfo);
// 用户信息的封装 implements UserDetails
UserinfoDetails memberDetails = new UserinfoDetails(userUserinfo);
return memberDetails;
}
@Autowired
private UserInfoFeignService userInfoFeignService;
public B8UserUserinfoEntity getByUsername(String username) {
// fegin获取用户信息
ResultData resultData = userInfoFeignService.getUserByUsername(username);
return resultData.getData();
}
}
UserInfoFeignService
package com.b8.auth.service;
import com.b8.auth.api.ResultData;
import com.b8.auth.service.impl.UserServiceHystrix;
import com.common.entity.po.B8UserUserinfoEntity;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
/**
-
@author zhiwei Liao
-
@version 1.0
-
@Description
-
@Date 2021/8/17 15:24
*/
@Component
@FeignClient(name = “user”, fallback = UserServiceHystrix.class, path = “/user”)
public interface UserInfoFeignService {
@GetMapping(“/getUserinfoById”)
ResultData getUserinfoById(@RequestParam(“userId”) String userId);
@GetMapping(“/getUserByUsername”)
ResultData getUserByUsername(@RequestParam(“username”) String username);
}
IErrorCode
package com.b8.auth.api;
/**
- 封装API的错误码
*/
public interface IErrorCode {
int getCode();
String getMessage();
}
ResultCode
package com.b8.auth.api;
/**
- 枚举了一些常用API操作码
*/
public enum ResultCode implements IErrorCode {
SUCCESS(200, “操作成功”),
FAILED(500, “操作失败”),
VALIDATE_FAILED(404, “参数检验失败”),
UNAUTHORIZED(401, “暂未登录或token已经过期”),
AUTHORIZATION_HEADER_IS_EMPTY(600,“请求头中的token为空”),
GET_TOKEN_KEY_ERROR(601,“远程获取TokenKey异常”),
GEN_PUBLIC_KEY_ERROR(602,“生成公钥异常”),
JWT_TOKEN_EXPIRE(603,“token校验异常”),
TOMANY_REQUEST_ERROR(429,“后端服务触发流控”),
BACKGROUD_DEGRADE_ERROR(604,“后端服务触发降级”),
BAD_GATEWAY(502,“网关服务异常”),
FORBIDDEN(403, “没有相关权限”);
private int code;
private String message;
private ResultCode(int code, String message) {
this.code = code;
this.message = message;
}
public int getCode() {
return code;
}
public String getMessage() {
return message;
}
}
ResultData
package com.b8.auth.api;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@NoArgsConstructor
public class ResultData implements Serializable {
/**
- 状态码
*/
public boolean status = true;
/**
- 状态码
*/
private Integer code = 200;
/**
- 接口返回信息
*/
private String msg;
/**
- 数据对象
*/
private T data;
/**
-
初始化一个新创建的 ResultData 对象
-
@param status 状态码
-
@param msg 返回内容
*/
public ResultData(Boolean status, String msg) {
this.status = status;
this.msg = msg;
}
/**
-
初始化一个新创建的 ResultData 对象
-
@param status 状态码
-
@param msg 返回内容
-
@param data 数据对象
*/
public ResultData(Boolean status, String msg, T data, Integer code) {
this.status = status;
this.msg = msg;
this.data = data;
this.code = code;
}
public ResultData(T data) {
this.data = data;
}
/**
-
返回成功消息
-
@param msg 返回内容
-
@param data 数据对象
-
@return 成功消息
*/
public static ResultData success(String msg, T data) {
return new ResultData(true, msg, data, 200);
}
/**
-
返回成功消息
-
@param msg 返回内容
-
@return 成功消息
*/
public static ResultData success(String msg) {
return ResultData.success(msg, null);
}
/**
-
返回成功消息
-
@return 成功消息
*/
public static ResultData success() {
return ResultData.success(null);
}
/**
-
返回成功数据
-
@return 成功消息
*/
public static ResultData success(T data) {
return ResultData.success(null, data);
}
/**
-
返回错误消息
-
@return
*/
public static ResultData error() {
return ResultData.error(null);
}
/**
-
返回错误消息
-
@param msg 返回内容
-
@return 警告消息
*/
public static ResultData error(String msg) {
return ResultData.error(msg, null);
}
/**
-
返回错误消息
-
@param code 状态码
-
@param msg 返回内容
-
@return 警告消息
*/
public static ResultData error(Integer code, String msg) {
return new ResultData(false, msg, null, code);
}
/**
-
返回错误消息
-
@param msg 返回内容
-
@param data 数据对象
-
@return 警告消息
*/
public static ResultData error(String msg, T data) {
return new ResultData(false, msg, data, 500);
}
}
B8AuthApplication
package com.b8.auth;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
最后
无论是哪家公司,都很重视基础,大厂更加重视技术的深度和广度,面试是一个双向选择的过程,不要抱着畏惧的心态去面试,不利于自己的发挥。同时看中的应该不止薪资,还要看你是不是真的喜欢这家公司,是不是能真的得到锻炼。
针对以上面试技术点,我在这里也做一些分享,希望能更好的帮助到大家。
《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》,点击传送门,即可获取!
error() {
return ResultData.error(null);
}
/**
-
返回错误消息
-
@param msg 返回内容
-
@return 警告消息
*/
public static ResultData error(String msg) {
return ResultData.error(msg, null);
}
/**
-
返回错误消息
-
@param code 状态码
-
@param msg 返回内容
-
@return 警告消息
*/
public static ResultData error(Integer code, String msg) {
return new ResultData(false, msg, null, code);
}
/**
-
返回错误消息
-
@param msg 返回内容
-
@param data 数据对象
-
@return 警告消息
*/
public static ResultData error(String msg, T data) {
return new ResultData(false, msg, data, 500);
}
}
B8AuthApplication
package com.b8.auth;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
最后
无论是哪家公司,都很重视基础,大厂更加重视技术的深度和广度,面试是一个双向选择的过程,不要抱着畏惧的心态去面试,不利于自己的发挥。同时看中的应该不止薪资,还要看你是不是真的喜欢这家公司,是不是能真的得到锻炼。
针对以上面试技术点,我在这里也做一些分享,希望能更好的帮助到大家。
[外链图片转存中…(img-ggB9vGIP-1714471676448)]
[外链图片转存中…(img-MwIHm3Ac-1714471676448)]
[外链图片转存中…(img-VRX0OaDD-1714471676449)]
《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》,点击传送门,即可获取!