SpringSecurity+Oauth2+JWT

这篇具有很好参考价值的文章主要介绍了SpringSecurity+Oauth2+JWT。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

SpringSecurity+Oauth2+JWT

快速入门

1. 创建基础项目

file ==> new ==> project ==> Spring Initializr ==>next ==> web(Spring Web)、Security(Spring Security) ==>一直下一步

2. 编写代码进行测试

创建controller

@Controller
public class LoginController {
    @RequestMapping("login")
    public String login(){
        System.out.println("登入成功!");
        return "redirect:main.html";
    }
}

static下创建login.html、main.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/login" method="post">
用户名:<input type="text" name="username"/><br/>
密码:<input type="password" name="password"/><br/>
    <input type="submit" value="登入" />
</form>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
登入成功!!!
</body>
</html>

3. 启动项目进行测试

访问http://localhost:8080/login.html

会进入SpringSecurity框架自带的登入页面 用户默认user 密码控制台生成 输入账号密码跳转到自己定义的login.html页面证明项目搭建完成

自定义登入

1. 定义SecurityConfig

@Configuration
public class SecurityConfig {
    @Bean
    public PasswordEncoder getPw(){
        return new BCryptPasswordEncoder();
    }
}

2. 定义UserDetailService实现类

@Service
public class UserDetailServiceImpl implements UserDetailsService {
    @Autowired
    private PasswordEncoder pw;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //根据用户名从数据库中取出用户 这里暂时写死
        if (!"admin".equals(username)){
            throw new UsernameNotFoundException("用户:"+username+"不存在");
        }
        //获取用户的密码 也暂时写死
        String root = pw.encode("root");
        return new User(username,root, 	      AuthorityUtils.commaSeparatedStringToAuthorityList("admin,normal"));
    }
}

3. 编写controller

	@RequestMapping("toMain")
    public String toMain(){
        return "redirect:main.html";
    }
    @RequestMapping("toError")
    public String toError(){
        return "redirect:error.html";
    }

4. 定义SecurityConfig类

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //表单提交
        http.formLogin()
                //当访问/login时认为是登入,执行loadUserByUsername方法
                .loginProcessingUrl("/login")
                //自定义登入页面
                .loginPage("/login.html")
                //登入成功的页面
                .successForwardUrl("/toMain")
                //登入失败
                .failureForwardUrl("/toError")
                ;


        /**
         * anyRequest          |   匹配所有请求路径
         * access              |   SpringEl表达式结果为true时可以访问
         * anonymous           |   匿名可以访问
         * denyAll             |   用户不能访问
         * fullyAuthenticated  |   用户完全认证可以访问(非remember-me下自动登录)
         * hasAnyAuthority     |   如果有参数,参数表示权限,则其中任何一个权限可以访问
         * hasAnyRole          |   如果有参数,参数表示角色,则其中任何一个角色可以访问
         * hasAuthority        |   如果有参数,参数表示权限,则其权限可以访问
         * hasIpAddress        |   如果有参数,参数表示IP地址,如果用户IP和参数匹配,则可以访问
         * hasRole             |   如果有参数,参数表示角色,则其角色可以访问
         * permitAll           |   用户可以任意访问
         * rememberMe          |   允许通过remember-me登录的用户访问
         * authenticated       |   用户登录后可访问
         */
        //授权认证
        http.authorizeRequests()
                .antMatchers("/login.html","/error.html").permitAll()
                //除上述请求任何请求都需要认证
                .anyRequest().authenticated();
        //关闭csrf防护
        http.csrf().disable();
    }

    @Bean
    //强散列哈希加密实现
    public PasswordEncoder getPw() {
        return new BCryptPasswordEncoder();
    }
}

自定义登入成功失败处理器

1. 定义AuthenticationSuccessHandler接口实现类、AuthenticationFailureHandler接口实现类

public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
    private String url;

    public MyAuthenticationSuccessHandler(String url) {
        this.url = url;
    }
    @Override
    public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
        httpServletResponse.sendRedirect(url);
    }
}
public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler {
    private String url;

    public MyAuthenticationFailureHandler(String url) {
        this.url = url;
    }


    @Override
    public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
        httpServletResponse.sendRedirect(url);
    }
}

2. 修改SecurityConfig配置类

        //表单提交
        http.formLogin()
                //当访问/login时认为是登入,执行loadUserByUsername方法
                .loginProcessingUrl("/login")
                //自定义登入页面
                .loginPage("/login.html")
//                //登入成功的页面
//                .successForwardUrl("/toMain")
                //自定义登入成功处理器 不能与successForwardUrl同时使用否侧报错
                .successHandler(new MyAuthenticationSuccessHandler("/main.html"))
//                //登入失败
//                .failureForwardUrl("/toError")
               .failureHandler(new MyAuthenticationFailureHandler("/error.html"));

权限判断

1. 根据权限进行过滤

//如果有参数,参数表示权限,则其中任何一个权限可以访问
.antMatchers("/main1.html").hasAnyAuthority("demo")
//如果有参数,参数表示权限,则其权限可以访问
.antMatchers("/main1.html").hasAuthority("demo")

2. 根据角色进行过滤

//如果有参数,参数表示角色,则其中任何一个角色可以访问
.antMatchers("/main1.html").hasAnyRole("test")
//如果有参数,参数表示角色,则其角色可以访问
.antMatchers("/main1.html").hasRole("test")

注意:配置角色时要以ROLE_为前缀

3. 根据ip进行过滤

.antMatchers("/main1.html").hasIpAddress("127.0.0.1")

自定义异常返回

1. 创建AccessDeniedHandler接口实现类

@Component
public class MyAccessDeniedHandler implements AccessDeniedHandler {
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
        //设置响应状态码
        response.setStatus(HttpServletResponse.SC_FORBIDDEN);
        response.setHeader("Content-Type","application/json;charset=utf-8");
        PrintWriter writer = response.getWriter();
        writer.write("{\"status\":\"error\",\"msg\":\"权限不足,请联系管理员\"}");
        writer.flush();
        writer.close();
    }
}

2. 配置SecurityConfig配置类

//异常处理
        http.exceptionHandling().accessDeniedHandler(myAccessDeniedHandler);

自定义方法实现权限控制

1. 编写接口

public interface MyService {
    boolean hasPermission(HttpServletRequest request, Authentication authentication);
}

2. 实现接口

@Service
public class MyServiceImpl implements MyService {
    @Override
    public boolean hasPermission(HttpServletRequest request, Authentication authentication) {
        //获取当前用户
        Object o = authentication.getPrincipal();
        if (o instanceof UserDetails){
            UserDetails userDetails = (UserDetails) o;
            Collection<? extends GrantedAuthority> authorities = userDetails.getAuthorities();
            //判断拥有权限是否包含
            return authorities.contains(new SimpleGrantedAuthority(request.getRequestURI()));
        }
        return false;
    }
}

3. 修改SecurityConfig配置类

.anyRequest().access("@myServiceImpl.hasPermission(request,authentication)");

注解实现权限控制

1. 启动类开启注解

@EnableGlobalMethodSecurity(securedEnabled = true)

2. controller接口上加注解

//拥有ROLE_test角色权限的用户可以访问
    //@Secured("ROLE_test")
	@PreAuthorize("hasRole('ROLE_test')")
    @RequestMapping("toMain1")
    public String toMain1(){
        return "redirect:main1.html";
    }

记住我实现

1. 所需依赖

 <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot</artifactId>
            <version>2.2.2</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

2. 配置数据源

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/security?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&verifyServerCertificate=false&useSSL=false&rewriteBatchedStatements=true
    username: root
    password: root

3. 配置SecurityConfig配置类

配置所需bean

    @Bean
    public PersistentTokenRepository getPersistentTokenRepository(){
        JdbcTokenRepositoryImpl repository = new JdbcTokenRepositoryImpl();
        repository.setDataSource(dataSource);
        //自动建表 建完表注释掉
        repository.setCreateTableOnStartup(true);
        return repository;
    }
 	@Autowired
    private UserDetailServiceImpl userDetailServiceImpl;

    @Autowired
    private DataSource dataSource;

    @Autowired
    private PersistentTokenRepository persistentTokenRepository;

configure()方法添加

        //记住我
        http.rememberMe()
                //设置过期时间 单位秒 默认两周
                .tokenValiditySeconds(30)
                .userDetailsService(userDetailServiceImpl)
                .tokenRepository(getPersistentTokenRepository())
                    //设置参数名称
//                .rememberMeParameter()
        ;

login.html新增记住我

<form action="/login" method="post">
    用户名:<input type="text" name="username"/><br/>
    密码:<input type="password" name="password"/><br/>
    记住我:<input type="checkbox" name="remember-me" value="true" /><br/>
    <input type="submit" value="登入" />
</form>

退出登入

1. 修改main.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
登入成功!!!<a href="/toMain1">跳转</a> <a href="/logout">退出</a>
</body>
</html>

2. 配置SecurityConfig配置类

		//退出登入
        http.logout().logoutSuccessUrl("/login.html");	

CSRF

CSRF 利用的是网站对用户网页浏览器的信任。跨站请求攻击,简单地说,是攻击者通过一些技术手段欺骗用户的浏览器去访问一个自己曾经认证过的网站并运行一些操作

默认开启生成一个类似于token的码进行身份识别

Oauth2认证

1. Oauth2认证流程:

  1. 客户端请求资源拥有者授权
  2. 资源拥有者返回授权码
  3. 客户端拿到授权码请求验证服务申请令牌
  4. 拿到令牌申请资源服务返回受保护资源

2. 术语

  1. 客户凭证:客户端的clientId和密码用于认证客户
  2. 令牌:授权服务器接收到客户端请求办法的令牌
  3. 作用域:客户端请求访问令牌时,由资源拥有者额外指定的细分权限
  4. 授权码:仅用于授权码授权类型,用于获取访问令牌和刷新令牌
  5. 访问令牌:相当于门禁卡,有了这个门禁卡就可以直接访问
  6. 刷新令牌:相当于刷新门禁卡的过期时间
  7. BearerToken:不管谁拿到Token都可以访问资源
  8. Proof of Possession Token:可以校验client是否对Token有明确的使用权

3. 四种模式

授权码模式、简易授权码模式、密码模式、客户端模式

Oauth2入门授权码模式

**1. ** 创建springboot项目 注入相关依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.csf</groupId>
    <artifactId>spring-security-oauth2</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-security-oauth2</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Greenwich.SR2</spring-cloud.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-oauth2</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
    </dependencies>
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

2. 创建定义登入

public class User implements UserDetails {
    private String username;
    private String password;
    public List<GrantedAuthority> authorities;

    public User(String username, String password, List<GrantedAuthority> authorities) {
        this.username = username;
        this.password = password;
        this.authorities = authorities;
    }

    @Override
    public List<GrantedAuthority> getAuthorities() {
        return authorities;
    }

    @Override
    public String getUsername() {
        return username;
    }

    @Override
    public String getPassword() {
        return password;
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }
}
@Service
public class UserService implements UserDetailsService {
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        String password = passwordEncoder.encode("123456");
        return new User("admin",password, AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
    }
}
@RestController
@RequestMapping("/user")
public class UserController {

    @RequestMapping("getUser")
    public Object getUser(Authentication authentication) {
        return authentication.getPrincipal();
    }
}

3. 创建SecurityConfig配置类

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Bean
    public PasswordEncoder getPas() {
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
        .authorizeRequests().antMatchers("/oauth/**","/login/**","/logout/**").permitAll()
        .anyRequest().authenticated()
        .and()
        .formLogin()
        .permitAll()
        ;

    }
}

4. 创建授权码服务配置类

/**
 * 授权码服务
 */
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                //配置用户名
                .withClient("admin")
                //配置密码
                .secret(passwordEncoder.encode("112233"))
                //配置Token访问有效期 单位秒
                .accessTokenValiditySeconds(3600)
                //配置授权成功跳转路径
                .redirectUris("http://www.baidu.com")
                //配置申请权限
                .scopes("all")
                //配置授权类型 authorization_code 授权码模式
                .authorizedGrantTypes("authorization_code")
        ;

    }
}

5. 创建资源服务配置类

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                //所有请求拦截
                .anyRequest().authenticated()
                .and()
                .requestMatchers()
                //放行
                .antMatchers("/user/**");
    }

}

6. 启动项目访问获取授权码

http://localhost:8902/oauth/authorize?response_type=code&client_id=admin&redirect_uri=http://www.baidu.com&scope=all

7. 拿到授权码访问http://localhost:8902/oauth/token 获取token

BasicAuth admin 112233
Boby grant_type authorization_code
code 授权码
client_id admin
redirect_uri http://www.baidu.com
scope all

Oauth2密码模式

1. SecurityConfig配置类新增bean

 @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

2. 修改AuthorizationServerConfig配置类

 @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private UserService userService;
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                //配置用户名
                .withClient("admin")
                //配置密码
                .secret(passwordEncoder.encode("112233"))
                //配置Token访问有效期 单位秒
                .accessTokenValiditySeconds(3600)
                //配置授权成功跳转路径
                .redirectUris("http://www.baidu.com")
                //配置申请权限
                .scopes("all")
                //配置授权类型 authorization_code 授权码模式 password密码模式
                .authorizedGrantTypes("password")
        ;

    }

    /**
     * 密码模式所需配置
     * @param endpoints
     * @throws Exception
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManager)
        .userDetailsService(userService);

    }
}

3. 测试 访问http://localhost:8902/oauth/token

BasicAuth admin 112233
Boby grant_type password
scope all
username admin
password 123456

4. token存入redis

配置redis

spring:
  redis:
    host: 127.0.0.1
    port: 6379

创建redis配置类

@Configuration
public class RedisConfig {
    @Resource
    private RedisConnectionFactory redisConnectionFactory;

    @Bean
    public TokenStore getTokenStore(){
        return new RedisTokenStore(redisConnectionFactory);
    }

}

修改AuthorizationServerConfig

    @Resource(name = "getTokenStore")
    private TokenStore tokenStore;
   @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManager)
        .userDetailsService(userService)
        .tokenStore(tokenStore);
    }

Jwt入门

1. 注入相关依赖

 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.0</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

2. 编写测试类

 void creatJwt() {
        long l = System.currentTimeMillis();
        l = l+(1*60*1000);
        JwtBuilder jwtBuilder = Jwts.builder()
        //声明标识
                .setId("8888")
                //主体
                .setSubject("Rose")
                //创建日期
                .setIssuedAt(new Date())
                //算法,盐
                .signWith(SignatureAlgorithm.HS256, "xxxx")
                //设置过期时间
                .setExpiration(new Date(l))
                //自定义
                .claim("name","常")
                .claim("mobile","999999999")
                ;
        String token = jwtBuilder.compact();
        System.out.println(token);
        System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
        String[] split = token.split("\\.");
        System.out.println(Base64Codec.BASE64.decodeToString(split[0]));
        System.out.println(Base64Codec.BASE64.decodeToString(split[1]));
        System.out.println(Base64Codec.BASE64.decodeToString(split[2]));


    }

3. token解密

void parsingToken(){
        String token = "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI4ODg4Iiwic3ViIjoiUm9zZSIsImlhdCI6MTY2NjMyMzYyMywiZXhwIjoxNjY2MzIzNjgzLCJuYW1lIjoi5bi4IiwibW9iaWxlIjoiOTk5OTk5OTk5In0.Hvmb8-qZydOwpM9yTI07EDxNxqQ06I2DAVyiYVQnlzY";
        Claims claims = Jwts.parser().setSigningKey("xxxx").parseClaimsJws(token).getBody();
        String id = claims.getId();
        String subject = claims.getSubject();
        Date issuedAt = claims.getIssuedAt();
        Date expiration = claims.getExpiration();
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println(id);
        System.out.println(subject);
        System.out.println(format.format(issuedAt));
        System.out.println(format.format(expiration));
        System.out.println(format.format(new Date()));
        System.out.println(claims.get("name"));
        System.out.println(claims.get("mobile"));

    }

Oauth2整合Jwt

1. 编写Jwt配置类

@Configuration
public class JwtTokenStoreConfig {
    @Bean
    public TokenStore jwtTokenStore(){
        return new JwtTokenStore(jwtAccessTokenConverter());
    }
    @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter(){
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        //配置密钥
        converter.setSigningKey("test_ket");
        return converter;
    }
}

2. 修改授权码服务配置类

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private UserService userService;
    @Resource(name = "jwtTokenStore")
    private TokenStore tokenStore;
    @Resource(name = "jwtAccessTokenConverter")
    private JwtAccessTokenConverter jwtAccessTokenConverter;


    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                //配置用户名
                .withClient("admin")
                //配置密码
                .secret(passwordEncoder.encode("112233"))
                //配置Token访问有效期 单位秒
//                .accessTokenValiditySeconds(3600)
                //配置授权成功跳转路径
//                .redirectUris("http://www.baidu.com")
                //配置申请权限
                .scopes("all")
                //配置授权类型 authorization_code 授权码模式 password密码模式
                .authorizedGrantTypes("password")
        ;

    }

    /**
     * 密码模式所需配置
     *
     * @param endpoints
     * @throws Exception
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManager)
                .userDetailsService(userService)
                .tokenStore(tokenStore)
                .accessTokenConverter(jwtAccessTokenConverter)
        ;
    }
}

Jwt扩展存储内容

1. 创建jwt增强器

public class JwtTokenEnhancer implements TokenEnhancer {
    @Override
    public OAuth2AccessToken enhance(OAuth2AccessToken oAuth2AccessToken, OAuth2Authentication oAuth2Authentication) {
        HashMap<String, Object> map = new HashMap<>();
        map.put("name","常");
        ((DefaultOAuth2AccessToken)oAuth2AccessToken).setAdditionalInformation(map);
        return oAuth2AccessToken;
    }
}

2. 修改Jwt配置类

@Configuration
public class JwtTokenStoreConfig {
    @Bean

    public TokenStore jwtTokenStore(){
        return new JwtTokenStore(jwtAccessTokenConverter());
    }
    @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter(){
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        //配置密钥
        converter.setSigningKey("test_ket");
        return converter;
    }
    @Bean
    public JwtTokenEnhancer jwtTokenEnhancer(){
       return new JwtTokenEnhancer();
    }
}

3. 修改AuthorizationServerConfig配置类

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private UserService userService;
    @Resource(name = "jwtTokenStore")
    private TokenStore tokenStore;
    @Resource(name = "jwtAccessTokenConverter")
    private JwtAccessTokenConverter jwtAccessTokenConverter;
    @Autowired
    private JwtTokenEnhancer jwtTokenEnhancer;


    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                //配置用户名
                .withClient("admin")
                //配置密码
                .secret(passwordEncoder.encode("112233"))
                //配置Token访问有效期 单位秒
//                .accessTokenValiditySeconds(3600)
                //配置授权成功跳转路径
//                .redirectUris("http://www.baidu.com")
                //配置申请权限
                .scopes("all")
                //配置授权类型 authorization_code 授权码模式 password密码模式
                .authorizedGrantTypes("password")
        ;

    }

    /**
     * 密码模式所需配置
     *
     * @param endpoints
     * @throws Exception
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        //jwt配置增强器
        TokenEnhancerChain enhancerChain = new TokenEnhancerChain();
        ArrayList<TokenEnhancer> list = new ArrayList<>();
        list.add(jwtTokenEnhancer);
        list.add(jwtAccessTokenConverter);
        enhancerChain.setTokenEnhancers(list);
        endpoints.authenticationManager(authenticationManager)
                .userDetailsService(userService)
                .tokenStore(tokenStore)
                .accessTokenConverter(jwtAccessTokenConverter)
                .tokenEnhancer(enhancerChain)
        ;
    }
}

Jwt解析

1. 注入依赖

		<dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.0</version>
        </dependency>
       

2. 测试

   @RequestMapping("getUser")
    public Object getUser(HttpServletRequest request) {
        String header = request.getHeader("Authentication");
        String[] split = header.split("Bearer ");
        String token = split[1];
        return Jwts.parser().setSigningKey("test_ket".getBytes(StandardCharsets.UTF_8)).parseClaimsJws(token).getBody();
    }

SpringSecurityOauth2整合SSO

1. 创建新springboot项目注入依赖

<properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Greenwich.SR2</spring-cloud.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-oauth2</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.0</version>
        </dependency>
    </dependencies>

Security+Jwt

1. 创建springboot工程注入相关依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.5</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.csf</groupId>
    <artifactId>spring-security-jwt</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-security-jwt</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--springSecurity跟jwt的依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security.oauth</groupId>
            <artifactId>spring-security-oauth2</artifactId>
            <version>2.3.5.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>
        <!--测试-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--mybatis‐plus的springboot支持-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.1.0</version>
        </dependency>
        <!--mysql驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.21</version>
        </dependency>
        <!--mysql依赖包-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--通过lombok包,实体类中不需要再写set,get方法,只需要添加一个@Data注解即可-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
            <scope>provided</scope>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

2. 配置数据源

server:
  port: 9001
logging:
  level:
    root: debug
spring:
  datasource:
    password: root
    username: root
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/security?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (
  `id` int(10) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) CHARACTER SET utf8 COLLATE utf8_german2_ci DEFAULT NULL,
  `password` varchar(255) CHARACTER SET utf8 COLLATE utf8_german2_ci DEFAULT NULL,
  `role` varchar(255) CHARACTER SET utf8 COLLATE utf8_german2_ci DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_german2_ci ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;

3. 创建JwtUser

public class JwtUser implements UserDetails {
    private Integer id;
    private String username;
    private String password;
    public Collection<? extends GrantedAuthority> authorities;

    //传入User构建JwtUser
    public JwtUser(User user) {
        id = user.getId();
        username = user.getUsername();
        password = user.getPassword();
        //权限
        authorities = Collections.singleton(new SimpleGrantedAuthority(user.getRole()));
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return authorities;
    }

    @Override
    public String getPassword() {
        return password;
    }

    @Override
    public String getUsername() {
        return username;
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }
}

4. JwtUtil

package com.csf.springsecurityjwt.util;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class JwtUtils {
    public static final String TOKEN_HEADER = "Authorization";
    public static final String TOKEN_PREFIX = "Bearer ";

    // TOKEN 过期时间
    public static final long EXPIRATION = 1000 * 60 * 30; // 三十分钟

    public static final String APP_SECRET_KEY = "secret";

    private static final String ROLE_CLAIMS = "rol";

    /**
     * 生成token
     *
     * @param username
     * @param role
     * @return
     */
    public static String createToken(String username, String role) {

        Map<String, Object> map = new HashMap<>();
        map.put(ROLE_CLAIMS, role);

        String token = Jwts
                .builder()
                .setSubject(username)
                .setClaims(map)
                .claim("username", username)
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION))
                .signWith(SignatureAlgorithm.HS256, APP_SECRET_KEY).compact();
        return token;
    }


    /**
     * 获取当前登录用户用户名
     *
     * @param token
     * @return
     */
    public static String getUsername(String token) {
        Claims claims = Jwts.parser().setSigningKey(APP_SECRET_KEY).parseClaimsJws(token).getBody();
        return claims.get("username").toString();
    }

    /**
     * 获取当前登录用户角色
     *
     * @param token
     * @return
     */
    public static String getUserRole(String token) {
        Claims claims = Jwts.parser().setSigningKey(APP_SECRET_KEY).parseClaimsJws(token).getBody();
        return claims.get("rol").toString();
    }

    /**
     * 获解析token中的信息
     *
     * @param token
     * @return
     */
    public static Claims checkJWT(String token) {
        try {
            final Claims claims = Jwts.parser().setSigningKey(APP_SECRET_KEY).parseClaimsJws(token).getBody();
            return claims;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    /**
     * 检查token是否过期
     *
     * @param token
     * @return
     */
    public static boolean isExpiration(String token) {
        Claims claims = Jwts.parser().setSigningKey(APP_SECRET_KEY).parseClaimsJws(token).getBody();
        return claims.getExpiration().before(new Date());
    }

}

5. 创建domain、mapper、service、controller

@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class User implements Serializable {

    private static final long serialVersionUID = 1L;

    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;

    private String username;

    private String password;

    private String role;
    
}
@Data
public class UserDto implements Serializable {
    private String username;

    private String password;
}

public interface UserMapper extends BaseMapper<User> {
}
public interface IUserService extends IService<User> {
    User findByUsername(String username);
}
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Override
    public User findByUsername(String username) {
        LambdaQueryWrapper<User> wrapper = new QueryWrapper<User>().lambda();
        wrapper.eq(User::getUsername,username);
        return getOne(wrapper);
    }
}
@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private IUserService userServiceImpl;
    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @PostMapping("saveUser")
    //添加账户
    public User saveUser(@RequestBody UserDto dto){
        User user = new User();
        BeanUtils.copyProperties(dto, user);
        user.setPassword(bCryptPasswordEncoder.encode(dto.getPassword()));
        //判断是否是admin账户
        if("admin".equals(dto.getUsername())){
            user.setRole("ADMIN");
        }else {
            user.setRole("USER");
        }
        userServiceImpl.save(user);
        return user;
    }
    @GetMapping("getUserByName")
    public User getUserByName(@RequestParam String username){
        return userServiceImpl.findByUsername(username);
    }

    @GetMapping("/findAll")
    @PreAuthorize("hasAnyAuthority('ADMIN')")  //这一步很重要 拥有ADMIN权限的用户才能访问该请求
    public List<User> findAll(){
        return userServiceImpl.list();
    }
}

6. 创建登入验证、SecurityConfig、拦截器

@Service
public class JwtUserServiceImpl implements UserDetailsService {
    @Autowired
    private IUserService userServiceImpl;

    @Override
    //根据用户传入的信息去数据库查询是否存在该用户
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userServiceImpl.findByUsername(username);
        if (user != null){
            JwtUser jwtUser = new JwtUser(user);
            return jwtUser;
        }else {
            try {
                throw new UsernameNotFoundException("用户不存在");
            } catch (UsernameNotFoundException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}
@EnableWebSecurity
// 只有加了@EnableGlobalMethodSecurity(prePostEnabled=true) 那么在上面使用的 @PreAuthorize(“hasAuthority(‘admin’)”)才会生效
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private JwtUserServiceImpl jwtUserServiceImpl;


    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * 这边 通过重写configure(),去数据库查询用户是否存在
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(jwtUserServiceImpl).passwordEncoder(bCryptPasswordEncoder());
    }
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().and().csrf().disable()
                .authorizeRequests()
                // 以/user 开头的请求 不需要进行验证
//                .antMatchers("/user/**").permitAll()
                // 其他都放行了
                .anyRequest().authenticated()
                .and()
                .addFilter(new JWTAuthenticationFilter(authenticationManager())) // 用户登录拦截
                .addFilter(new JWTAuthorizationFilter(authenticationManager()))  // 权限拦截
                // 不需要session
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .exceptionHandling();
    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues());
        return source;
    }


}

/**
 * 验证用户名密码正确后,生成一个token,并将token返回给客户端
 * 该类继承自UsernamePasswordAuthenticationFilter,重写了其中的2个方法 ,
 * attemptAuthentication:接收并解析用户凭证。
 * successfulAuthentication:用户成功登录后,这个方法会被调用,我们在这个方法里生成token并返回。
 */
public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

    private AuthenticationManager authenticationManager;

    /**
     * security拦截默认是以POST形式走/login请求,我们这边设置为走/token请求
     * @param authenticationManager
     */
    public JWTAuthenticationFilter(AuthenticationManager authenticationManager) {
        this.authenticationManager = authenticationManager;
        super.setFilterProcessesUrl("/login");
    }

    /**
     * 接收并解析用户凭证
     * @param request
     * @param response
     * @return
     * @throws AuthenticationException
     */
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request,
                                                HttpServletResponse response) throws AuthenticationException {

        // 从输入流中获取到登录的信息
        try {
            User loginUser = new ObjectMapper().readValue(request.getInputStream(), User.class);
            return authenticationManager.authenticate(
                    new UsernamePasswordAuthenticationToken(loginUser.getUsername(), loginUser.getPassword())
            );
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    // 成功验证后调用的方法
    // 如果验证成功,就生成token并返回
    @Override
    protected void successfulAuthentication(HttpServletRequest request,
                                            HttpServletResponse response,
                                            FilterChain chain,
                                            Authentication authResult) throws IOException, ServletException {

        JwtUser jwtUser = (JwtUser) authResult.getPrincipal();
        System.out.println("jwtUser:" + jwtUser.toString());

        String role = "";
        Collection<? extends GrantedAuthority> authorities = jwtUser.getAuthorities();
        for (GrantedAuthority authority : authorities) {
            role = authority.getAuthority();
        }

        String token = JwtUtils.createToken(jwtUser.getUsername(), role);
        // 返回创建成功的token  但是这里创建的token只是单纯的token
        // 按照jwt的规定,最后请求的时候应该是 `Bearer token`
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        String tokenStr = JwtUtils.TOKEN_PREFIX + token;
        response.setHeader("token", tokenStr);
    }

    // 失败 返回错误就行
    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
        response.getWriter().write("authentication failed, reason: " + failed.getMessage());
    }

}
public class JWTAuthorizationFilter extends BasicAuthenticationFilter {

    public JWTAuthorizationFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
    }

    @SneakyThrows
    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain chain) throws IOException, ServletException {

        String tokenHeader = request.getHeader(JwtUtils.TOKEN_HEADER);
        // 如果请求头中没有Authorization信息则直接放行了
        if (tokenHeader == null || !tokenHeader.startsWith(JwtUtils.TOKEN_PREFIX)) {
            chain.doFilter(request, response);
            return;
        }
        // 如果请求头中有token,则进行解析,并且设置认证信息
        SecurityContextHolder.getContext().setAuthentication(getAuthentication(tokenHeader));
        super.doFilterInternal(request, response, chain);
    }

    // 这里从token中获取用户信息并新建一个token 就是上面说的设置认证信息
    private UsernamePasswordAuthenticationToken getAuthentication(String tokenHeader) throws Exception {

        String token = tokenHeader.replace(JwtUtils.TOKEN_PREFIX, "");

        // 检测token是否过期 如果过期会自动抛出错误
        JwtUtils.isExpiration(token);
        String username = JwtUtils.getUsername(token);
        String role = JwtUtils.getUserRole(token);
        if (username != null) {
            return new UsernamePasswordAuthenticationToken(username, null,
                    Collections.singleton(new SimpleGrantedAuthority(role))
            );
        }
        return null;
    }

}

7. 启动项目开始测试文章来源地址https://www.toymoban.com/news/detail-518931.html

到了这里,关于SpringSecurity+Oauth2+JWT的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 权限认证SpringCloud GateWay、SpringSecurity、OAuth2.0、JWT一网打尽!

    1.它是如何工作的? ​ 客户端向 Spring Cloud Gateway 发出请求。如果Gateway处理程序映射确定一个请求与路由相匹配,它将被发送到Gateway Web处理程序。这个处理程序通过一个特定于该请求的过滤器链来运行该请求。过滤器被虚线分割的原因是,过滤器可以在代理请求发送之前和

    2024年04月08日
    浏览(44)
  • SpringSecurity学习(八)OAuth2.0、授权服务器、资源服务器、JWT令牌的使用

    OAuth2是一个认证协议,SpringSecurity对OAuth2协议提供了响应的支持,开发者可以非常方便的使用OAuth2协议。 简介 四种授权模式 Spring Security OAuth2 GitHub授权登录 授权服务器与资源服务器 使用JWT OAuth是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密资源

    2024年02月02日
    浏览(56)
  • SpringSecurity+OAuth2.0

    OAuth(Open Authorization)是一个关于授权(authorization)的开放网络标准,允许用户授权第三方应用访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方移动应用或分享他们数据的所有内容。OAuth 在全世界得到广泛应用,目前的版本是 2.0 版。 简单

    2024年02月13日
    浏览(38)
  • SpringSecurity之Oauth2介绍

    第三方认证技术方案最主要是解决 认证协议的通用标准问题 ,因为要实现跨系统认证,各系统之间要遵循一定的接口协议。 OAUTH协议为用户资源的授权提供了一个安全的、开放而又简易的标准。同时,任何第三方都可以使用OAUTH认证服务,任何服务提供商都可以实现自身的

    2023年04月09日
    浏览(42)
  • SpringSecurity +oauth2获取当前登录用户(二)

    特别注意:以下内容如果访问失败或有其他疑问,可先学习: SpringSecurity +oauth2+JWT实现统一授权和认证及项目搭建(一) 1 获取当前用户的信息代码为: 但是,通过运行会发现principal的值只是 用户名 ,没有用户信息,通过去看源码,才发现问题所在,以下是源码: 源码类:

    2023年04月12日
    浏览(47)
  • SpringSecurity OAuth2 配置 token有效时长

    1.这种方式配置之后,并没有生效 2.第二种方法时改数据库的配置,测试配置有效

    2024年02月09日
    浏览(47)
  • JWT和OAuth2.0

    JWT和OAuth2.0没有可比性,是两个完全不同的东西。 JWT是一种认证协议,提供了一种用于发布接入令牌(Access Token),并对发布的签名接入令牌进行验证的方法。SSO私钥加密token。应用端公钥解密token, OAuth2.0是一种授权框架,提供了一套详细的授权机制(指导)。用户或应用可以通

    2023年04月16日
    浏览(42)
  • springboot整合springsecurity+oauth2.0密码授权模式

    本文采用的springboot去整合springsecurity,采用oauth2.0授权认证,使用jwt对token增强。本文仅为学习记录,如有不足多谢提出。 OAuth 2.0是用于授权的行业标准协议。OAuth 2.0为简化客户端开发提供了特定的授权流,包括Web应用、桌面应用、移动端应用等。 Resource owner(资源拥有者)

    2024年02月04日
    浏览(57)
  • 五、SpringSecurity OAuth2扩展手机验证码授权模式

    代码仓库:地址 代码分支:lesson5 在上一篇文章中,我们使用SpringSecurity OAuth2搭建了一套授权服务,对业务系统进行统一授权管理。OAuth提供了四种授权方式: 授权码模式(authorization_code) 简化模式(implicit) 客户端(client_credentials) 密码(password) 在实际业务中上述四种模式不

    2024年02月11日
    浏览(54)
  • SpringSecurity+OAuth2.0 搭建认证中心和资源服务中心

    目录   1. OAuth2.0 简介 2. 代码搭建  2.1 认证中心(8080端口) 2.2 资源服务中心(8081端口) 3. 测试结果   OAuth 2.0(开放授权 2.0)是一个开放标准,用于授权第三方应用程序访问用户在资源所有者(用户)的帐户上存储的受保护资源,而无需共享用户凭据。OAuth 2.0 主要用于在

    2024年01月22日
    浏览(61)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包