當前位置:
首頁 > 知識 > Spring security + oauth2.0 + redis + mybatis plus 搭建微服務

Spring security + oauth2.0 + redis + mybatis plus 搭建微服務

上個星期一個朋友請求幫忙,讓我搭建一個分散式授權中心的微服務,之前我也沒搭建過,在網上擼了幾天前輩們寫的技術博客,搞出個模型,分享給大家:

前輩們博客地址:

OAuth2.0 原理:https://blog.csdn.net/tclzsn7456/article/details/79550249

JWT 原理:https://baijiahao.baidu.com/s?id=1608021814182894637&wfr=spider&for=pc

以下是代碼,我這個是通過密碼模式進行認證的:

0.目錄結構:

Spring security + oauth2.0 + redis + mybatis plus 搭建微服務

打開今日頭條,查看更多圖片

1.引入依賴:

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</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-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>4.3.1</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.0.7.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>

2.編寫配置類 AuthorizationParam 並在application.yml 中填寫具體參數:

@Data
@ConfigurationProperties(prefix = "authorizationparam")
public class AuthorizationParam {
private String clientId; //客戶端id
private String secret; //(可信客戶端需要)客戶端密鑰
private String[] scopes; //客戶受限範圍
private String authorizedGrantTypes; // 授權客戶端使用的授權類型
// private String authorities;//授予客戶端的許可權
private int tokenExpire;//token過期時間
private int tokenRefresh;//token 刷新時間
}

在application.yml 中填寫具體參數:

authorizationparam:
client-id: 123456 #客戶端id
secret: 123456 #(可信客戶端需要)客戶端密鑰
scopes: read,write #客戶受限範圍
authorized-grant-types: password #授權客戶端使用的授權類型
token-expire: 10000 #token過期時間
token-refresh: 1500 #token刷新時間
debug: true

3.編寫OAuth2.0配置類,注意,這裡我使用redis來存儲令牌(token)和具體的用戶信息,這邊便於後期水平擴張:

package com.lmolong.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.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;
/***
* OAuth 相關配置
*/
@Configuration
@EnableAuthorizationServer
public class OAuth2AuthorizationConfig extends AuthorizationServerConfigurerAdapter {
private static final String SECRETPREFIX = "{noop}"; //spring security5 之後需要
@Autowired
private AuthenticationManager authenticationManager; //認證管理者
@Autowired
private UserDetailsService userDetailsService; // 用戶信息服務
@Autowired
private TokenStore tokenStore; //保存令牌數據棧
@Autowired
private AuthorizationParam authorizationParam;
@Override
public void configure(ClientDetailsServiceConfigurer clents) throws Exception {
clents.inMemory()
.withClient(authorizationParam.getClientId()) //客戶端ID
.authorizedGrantTypes(authorizationParam.getAuthorizedGrantTypes(),"refresh_token")//設置驗證方式
.scopes(authorizationParam.getScopes())
// .secret("{noop}secret")
.secret(SECRETPREFIX+authorizationParam.getSecret())
.accessTokenValiditySeconds(authorizationParam.getTokenExpire()) //token過期時間
.refreshTokenValiditySeconds(authorizationParam.getTokenRefresh());//refresh過期時間
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints){
endpoints.tokenStore(tokenStore)
.authenticationManager(authenticationManager)
.userDetailsService(userDetailsService);
}
@Bean
public TokenStore tokenStore(RedisConnectionFactory redisConnectionFactory){
// return new InMemoryTokenStore(); //使用內存存儲令牌 tokeStore
return new RedisTokenStore(redisConnectionFactory); //使用redis存儲令牌
}
}

4.編寫web攔截、資源攔截 配置:

package com.lmolong.config;
import cn.hutool.crypto.SecureUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.configuration.GlobalAuthenticationConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
public class WebSecurityConfiguration extends GlobalAuthenticationConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Override
public void init(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService)
.passwordEncoder(new PasswordEncoder() {
@Override
public String encode(CharSequence charSequence)
{
return charSequence.toString();
//return SecureUtil.md5(charSequence.toString());
}
@Override
public boolean matches(CharSequence charSequence, String s) {
//return SecureUtil.md5(charSequence.toString()).equals(s);
return charSequence.toString().equals(s);
}
});
// auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder()).withUser("user1").password(new BCryptPasswordEncoder().encode("123456")).roles("USER");
}
}

package com.lmolong.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
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 ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS).permitAll()
.anyRequest().authenticated()
.and().httpBasic()
.and().csrf().disable();
}
}

5.這裡配置密碼的加密方式,這裡我暫時未加密:

package com.lmolong.config;
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.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
//對任何請求做攔截,如果是完整認證的話,就允許訪問
http.authorizeRequests().anyRequest().fullyAuthenticated();
//配置登陸連接,允許訪問 --認證介面直接調用/oauth/token
http.formLogin().loginPage("/login").failureUrl("/login?code=").permitAll();
//配置登出連接,允許訪問
http.logout().logoutUrl("/logout").permitAll();
http.authorizeRequests().antMatchers("/oauth/authorize").permitAll();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
super.configure(auth);
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}

6.擴張UserDetailService

package com.lmolong.service;
import org.springframework.security.core.userdetails.UserDetailsService;
//後期在此新增UserService的業務介面
public interface UserService extends UserDetailsService {
}

7.實現 UserService,擴展用戶認證功能:

package com.lmolong.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.lmolong.authbean.AuthUserDetail;
import com.lmolong.mapper.TUserMapper;
import com.lmolong.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import com.lmolong.pojo.TUser;
@Primary
@Service
public class UserServiceImpl implements UserService {
@Autowired
private TUserMapper tUserMapper;
@Override
public AuthUserDetail loadUserByUsername(String username) throws UsernameNotFoundException {
TUser param =new TUser();
param.setUsername(username);
TUser tUser = tUserMapper.selectOne(new QueryWrapper<>(param));
if(tUser==null){
throw new UsernameNotFoundException("用戶不存在");
}else{
return UserDetailConverter.convert(tUser);
}
}
private static class UserDetailConverter {
static AuthUserDetail convert(TUser user) {
return new AuthUserDetail(user);
}
}
}

8.編寫認證資料庫實體類,注意,這裡我用了lombok:

package com.lmolong.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class TUser implements Serializable {
private Long id;
private String username;
private String password;
}

9.對應的Auth2.0許可權封裝類:

package com.lmolong.authbean;
import lombok.Data;
import org.springframework.security.core.userdetails.User;
import com.lmolong.pojo.TUser;
import java.util.Collections;
@Data
public class AuthUserDetail extends User {
private TUser tUser;
public AuthUserDetail(TUser user) {
super(user.getUsername(), user.getPassword(), true, true, true, true, Collections.EMPTY_SET);
this.tUser= user;
}
}

10.編寫對應mapper介面:

package com.lmolong.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.lmolong.pojo.TUser;
public interface TUserMapper extends BaseMapper<TUser> {
}

11.注意,在啟動類中,我們要加上MapperScan註解:

package com.lmolong;

import com.lmolong.config.AuthorizationParam;

import org.mybatis.spring.annotation.MapperScan;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.boot.context.properties.EnableConfigurationProperties;

@SpringBootApplication

@EnableConfigurationProperties({AuthorizationParam.class})

@MapperScan("com.lmolong.mapper")

public class SpringcloudOauth2Application {

public static void main(String[] args) {

SpringApplication.run(SpringcloudOauth2Application.class, args);

}

}

12.編寫獲取用戶信息介面:

package com.lmolong.controller;
import com.lmolong.authbean.AuthUserDetail;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;
import com.lmolong.pojo.TUser;
@RestController
public class UserController {
@Autowired
private TokenStore tokenStore;
@PostMapping("/auth")
public String auth(@RequestHeader("Authorization") String auth){
AuthUserDetail authUserDetail = (AuthUserDetail) tokenStore.readAuthentication(auth.split(" ")[1]).getPrincipal();
TUser tUser = authUserDetail.getTUser();
return tUser.getUsername()+":"+tUser.getPassword();
}
}

13.測試:

通過postman調用:http://localhost:8080/oauth/token 獲取令牌

Spring security + oauth2.0 + redis + mybatis plus 搭建微服務

獲取token成功:

Spring security + oauth2.0 + redis + mybatis plus 搭建微服務

使用 Redis Desktop manager 查看數據,發現數據已經存到redis中了:

Spring security + oauth2.0 + redis + mybatis plus 搭建微服務

訪問介面,根據token獲取用戶信息:

Spring security + oauth2.0 + redis + mybatis plus 搭建微服務

獲取成功。

至此,這個授權微服務整合完畢,當然,可能還有很多不完善的地方,期待大神指導,讓我能更加完善它,在此感謝。

源碼地址:https://gitee.com/lmolong/springcloud-oauth2

作者:L墨龍

原文:https://my.oschina.net/linwl/blog/2998036

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 程序員小新人學習 的精彩文章:

基於ng-zorro的ASP.NET ZERO前端實現
Linux/CentOS安裝MySQL(RPM安裝、編譯安裝)

TAG:程序員小新人學習 |