Demo:第三章:权限框架spring security oauth2

@Autowired

@Qualifier(“jwtTokenStore”)

private TokenStore tokenStore;

@Autowired

private JwtAccessTokenConverter jwtAccessTokenConverter;

@Autowired

private B8AuthUserDetailService userDetailService;

@Autowired

private AuthenticationManager authenticationManagerBean;

@Autowired

private B8AuthTokenEnhancer b8AuthTokenEnhancer;

/**

  • @Description 第三方信息的存储

  • @MethodParameterTypes [org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer]

  • @MethodParameters [clients]

  • @MethodReturnType void

  • @Author zhiwei Liao

  • @Date 2021/8/17 14:57

**/

@Override

public void configure(ClientDetailsServiceConfigurer clients) throws Exception {

// 第三方信息的存储 基于jdbc

clients.withClientDetails(clientDetailsService());

}

@Override

public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {

//配置JWT的内容增强器

TokenEnhancerChain enhancerChain = new TokenEnhancerChain();

List delegates = new ArrayList<>();

delegates.add(b8AuthTokenEnhancer);

delegates.add(jwtAccessTokenConverter);

enhancerChain.setTokenEnhancers(delegates);

//使用密码模式需要配置

endpoints.authenticationManager(authenticationManagerBean)

.reuseRefreshTokens(false) //refresh_token是否重复使用

.userDetailsService(userDetailService) //刷新令牌授权包含对用户信息的检查

.tokenStore(new JdbcTokenStore(dataSource)) //指定token存储策略是jwt,存储到mysql

.accessTokenConverter(jwtAccessTokenConverter)

.tokenEnhancer(enhancerChain) //配置tokenEnhancer

.allowedTokenEndpointRequestMethods(HttpMethod.GET,HttpMethod.POST); //支持GET,POST请求

}

@Bean

public JdbcTokenStore jdbcTokenStore(){

return new JdbcTokenStore(dataSource);

}

/**

  • 授权服务器安全配置

  • @param security

  • @throws Exception

*/

@Override

public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {

//第三方客户端校验token需要带入 clientId 和clientSecret来校验

security.checkTokenAccess(“isAuthenticated()”)

.tokenKeyAccess(“isAuthenticated()”);//来获取我们的tokenKey需要带入clientId,clientSecret

//允许表单认证

security.allowFormAuthenticationForClients();

}

@Bean

public ClientDetailsService clientDetailsService(){

return new JdbcClientDetailsService(dataSource);

}

}

AuthResourceServerConfig

package com.b8.auth.config;

import org.springframework.context.annotation.Configuration;

import org.springframework.security.config.annotation.web.builders.HttpSecurity;

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;

/**

必看视频!获取2024年最新Java开发全套学习资料 备注Java

  • 证书存储密钥

*/

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);

总结

我们总是喜欢瞻仰大厂的大神们,但实际上大神也不过凡人,与菜鸟程序员相比,也就多花了几分心思,如果你再不努力,差距也只会越来越大。

面试题多多少少对于你接下来所要做的事肯定有点帮助,但我更希望你能透过面试题去总结自己的不足,以提高自己核心技术竞争力。每一次面试经历都是对你技术的扫盲,面试后的复盘总结效果是极好的!

/**

  • 接口返回信息

*/

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);

总结

我们总是喜欢瞻仰大厂的大神们,但实际上大神也不过凡人,与菜鸟程序员相比,也就多花了几分心思,如果你再不努力,差距也只会越来越大。

面试题多多少少对于你接下来所要做的事肯定有点帮助,但我更希望你能透过面试题去总结自己的不足,以提高自己核心技术竞争力。每一次面试经历都是对你技术的扫盲,面试后的复盘总结效果是极好的!

[外链图片转存中…(img-VT3efCv2-1716406720023)]

  • 20
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值