写点什么

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

  • 2022 年 4 月 28 日
  • 本文字数:6239 字

    阅读完需:约 20 分钟

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


.antMa 《一线大厂 Java 面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》无偿开源 威信搜索公众号【编程进阶路】 tchers("/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<B8UserUserinfoEntity> getUserinfoById(String userId) {


return null;


}


@Override


public ResultData<B8UserUserinfoEntity> 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<B8UserUserinfoEntity> 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<B8UserUserinfoEntity> getUserinfoById(@RequestParam("userId") String userId);


@GetMapping("/getUserByUsername")


ResultData<B8UserUserinfoEntity> 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<T> 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 <T> ResultData<T> success(String msg, T data) {


return new ResultData<T>(true, msg, data, 200);


}


/**


  • 返回成功消息

  • @param msg 返回内容

  • @return 成功消息


*/


public static <T> ResultData<T> success(String msg) {


return ResultData.success(msg, null);


}


/**


  • 返回成功消息

  • @return 成功消息


*/


public static <T> ResultData<T> success() {


return ResultData.success(null);


}


/**


  • 返回成功数据

  • @return 成功消息


*/


public static <T> ResultData<T> success(T data) {


return ResultData.success(null, data);


}


/**


  • 返回错误消息

  • @return


*/


public static <T> ResultData<T> error() {


return ResultData.error(null);


}


/**


  • 返回错误消息

  • @param msg 返回内容

  • @return 警告消息


*/


public static <T> ResultData<T> error(String msg) {


return ResultData.error(msg, null);


}

用户头像

还未添加个人签名 2022.04.13 加入

还未添加个人简介

评论

发布
暂无评论
Demo:第三章:权限框架spring security oauth2_程序员_爱好编程进阶_InfoQ写作社区