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

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

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

最后

关于面试刷题也是有方法可言的,建议最好是按照专题来进行,然后由基础到高级,由浅入深来,效果会更好。当然,这些内容我也全部整理在一份pdf文档内,分成了以下几大专题:

  • Java基础部分

  • 算法与编程

  • 数据库部分

  • 流行的框架与新技术(Spring+SpringCloud+SpringCloudAlibaba)

这份面试文档当然不止这些内容,实际上像JVM、设计模式、ZK、MQ、数据结构等其他部分的面试内容均有涉及,因为文章篇幅,就不全部在这里阐述了。

作为一名程序员,阶段性的学习是必不可少的,而且需要保持一定的持续性,这次在这个阶段内,我对一些重点的知识点进行了系统的复习,一方面巩固了自己的基础,另一方面也提升了自己的知识广度和深度。
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

@SpringBootApplication

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。[外链图片转存中…(img-yQbnsuZ3-1713319524952)]

[外链图片转存中…(img-UXByvCYg-1713319524952)]

[外链图片转存中…(img-PsQLbVDU-1713319524953)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

最后

关于面试刷题也是有方法可言的,建议最好是按照专题来进行,然后由基础到高级,由浅入深来,效果会更好。当然,这些内容我也全部整理在一份pdf文档内,分成了以下几大专题:

  • Java基础部分

[外链图片转存中…(img-VjEs3krI-1713319524953)]

  • 算法与编程

[外链图片转存中…(img-nmOhiJFz-1713319524953)]

  • 数据库部分

[外链图片转存中…(img-6UOPllSX-1713319524953)]

  • 流行的框架与新技术(Spring+SpringCloud+SpringCloudAlibaba)

[外链图片转存中…(img-u7YmksMX-1713319524954)]

这份面试文档当然不止这些内容,实际上像JVM、设计模式、ZK、MQ、数据结构等其他部分的面试内容均有涉及,因为文章篇幅,就不全部在这里阐述了。

作为一名程序员,阶段性的学习是必不可少的,而且需要保持一定的持续性,这次在这个阶段内,我对一些重点的知识点进行了系统的复习,一方面巩固了自己的基础,另一方面也提升了自己的知识广度和深度。
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值