一、授权码认证流程图


(A)用户访问客户端,后者将前者导向认证服务器。
(B)用户选择是否给予客户端授权。
(C)假设用户给予授权,认证服务器将用户导向客户端事先指定的"重定向URI"(redirection URI),同时附上一个授权码。
(D)客户端收到授权码,附上早先的"重定向URI",向认证服务器申请令牌。这一步是在客户端的后台的服务器上完成的,对用户不可见。
(E)认证服务器核对了授权码和重定向URI,确认无误后,向客户端发送访问令牌(access token)和更新令牌(refresh token)。

二、授权码认证的优缺点

三、依赖配置(使用spring-cloud)

<dependencies><!--nacos 注册中心--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!--nacos 配置中心--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency><!--redis--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis-reactive</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-freemarker</artifactId></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.58</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.10</version></dependency><!--mysql 驱动--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.49</version></dependency><!--使用 mybatis-plus 作为数据库持久层框架--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.2.0</version></dependency><!--加入代码生成器的依赖--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-generator</artifactId><version>3.3.1.tmp</version></dependency><!--加入模板引擎的依赖--><dependency><groupId>org.apache.velocity</groupId><artifactId>velocity-engine-core</artifactId><version>2.2</version></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-oauth2</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope><exclusions><exclusion><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId></exclusion></exclusions></dependency></dependencies><dependencyManagement><!--springCloud  基础依赖配置 很重要,如果没有,springCloud 就用不了--><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency><!--spring-cloud-alibaba 基础依赖配置,很重要,如果没有,nacos 等一些组件就使用不了--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>0.2.2.RELEASE</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>

四、使用mybatis-plus自动生成代码


public class CodeGenerator {//程序入口public static void main(String[] args) {//创建代码生成器对象AutoGenerator mpg = new AutoGenerator();//全局设置GlobalConfig gc = new GlobalConfig();//设置输出路径gc.setOutputDir(System.getProperty("user.dir") + "/jyshop-test/src/main/java");//设置作者gc.setAuthor("liuhao");//生成是否打开文件gc.setOpen(false);//全局设置mpg.setGlobalConfig(gc);//设置生成返回的结果集gc.setBaseResultMap(true);gc.setBaseColumnList(true);//数据源配置DataSourceConfig dsc = new DataSourceConfig();//设置驱动类dsc.setDriverName("com.mysql.jdbc.Driver");//设置的urldsc.setUrl("jdbc:mysql://localhost:3306/1707a?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=UTC");//设置用户名dsc.setUsername("root");//设置密码dsc.setPassword("root");//设置代码生成器对象的数据mpg.setDataSource(dsc);//设置生成到到哪里 包PackageConfig pc = new PackageConfig();//设置包名称pc.setParent(CodeGenerator.class.getPackage().getName());//设置包的路径com.bawei.bootplus /entity/service/mapper/controllermpg.setPackageInfo(pc);//生成的策略StrategyConfig strategy = new StrategyConfig();//生成那些表strategy.setInclude("t_user");//排除表//strategy.setExclude("t_user");//表的前缀strategy.setTablePrefix("t_");//strategy.setFieldPrefix()//采用lombok处理strategy.setEntityLombokModel(true);//设置生成策略mpg.setStrategy(strategy);//执行生成mpg.execute();}
}

五、需要添加的配置类

AuthorizationServerConfig类

package com.liuhao.demo.config.oauth;import com.liuhao.demo.service.impl.TUserServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.password.PasswordEncoder;
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.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;import javax.annotation.Resource;/*** 〈OAuth2认证服务器〉** @author Curise* @create 2018/12/13* @since 1.0.0*/
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {@Autowiredprivate AuthenticationManager authenticationManager;@Autowiredprivate RedisConnectionFactory redisConnectionFactory;@Autowiredprivate TUserServiceImpl userDetailService;@Beanpublic TokenStore tokenStore() {return new RedisTokenStore(redisConnectionFactory);}/*** 所有的请求必须要经过oauth2.0 认证服务器 要校验access_token 的有效性* @param security* @throws Exception*/@Overridepublic void configure(AuthorizationServerSecurityConfigurer security) throws Exception {security.allowFormAuthenticationForClients().tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");}@Resourceprivate PasswordEncoder passwordEncoder;/*** 定义客户端在进行认证的时候需要传递的 参数  包括了* withClient* secret 密钥* oauth2.0 的模式* 访问的作用域* 认证成功需要颁发的access_token,refresh_token* @param clients* @throws Exception*/@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {//clients.withClientDetails(clientDetails());clients.inMemory().withClient("android").scopes("read").secret(passwordEncoder.encode("android")).authorizedGrantTypes("password", "authorization_code", "refresh_token").and().withClient("webapp").scopes("read").authorizedGrantTypes("implicit").and().withClient("browser").authorizedGrantTypes("refresh_token", "password").scopes("read");}/*** 配置token 的存储规则* @param endpoints* @throws Exception*/@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {//配置access_token 存储规则endpoints.tokenStore(tokenStore()).userDetailsService(userDetailService)//定义用户名和密码的校验.authenticationManager(authenticationManager);//权限管理器 使用默认的权限管理器endpoints.tokenServices(defaultTokenServices());//token 生成规则//认证异常翻译// endpoints.exceptionTranslator(webResponseExceptionTranslator());}/*** <p>注意,自定义TokenServices的时候,需要设置@Primary,否则报错,</p>* @return*/@Primary@Beanpublic DefaultTokenServices defaultTokenServices(){DefaultTokenServices tokenServices = new DefaultTokenServices();tokenServices.setTokenStore(tokenStore());tokenServices.setSupportRefreshToken(true);// token有效期自定义设置,默认12小时tokenServices.setAccessTokenValiditySeconds(60*60*12);// refresh_token默认30天tokenServices.setRefreshTokenValiditySeconds(60 * 60 * 24 * 7);return tokenServices;}
}

RedisTokenStore类

package com.liuhao.demo.config.oauth;import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.oauth2.common.ExpiringOAuth2RefreshToken;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2RefreshToken;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.AuthenticationKeyGenerator;
import org.springframework.security.oauth2.provider.token.DefaultAuthenticationKeyGenerator;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.redis.JdkSerializationStrategy;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStoreSerializationStrategy;
import org.springframework.stereotype.Component;import java.util.*;/*** 〈重写RedisTokenStore〉*  spring5.0修改了一些方法,导致不兼容,需要重写全部的set()为stringCommands().set()* @author Curise* @create 2018/12/17* @since 1.0.0*/
@Component
public class RedisTokenStore implements TokenStore {private static final String ACCESS = "access:";private static final String AUTH_TO_ACCESS = "auth_to_access:";private static final String AUTH = "auth:";private static final String REFRESH_AUTH = "refresh_auth:";private static final String ACCESS_TO_REFRESH = "access_to_refresh:";private static final String REFRESH = "refresh:";private static final String REFRESH_TO_ACCESS = "refresh_to_access:";private static final String CLIENT_ID_TO_ACCESS = "client_id_to_access:";private static final String UNAME_TO_ACCESS = "uname_to_access:";private final RedisConnectionFactory connectionFactory;private AuthenticationKeyGenerator authenticationKeyGenerator = new DefaultAuthenticationKeyGenerator();private RedisTokenStoreSerializationStrategy serializationStrategy = new JdkSerializationStrategy();private String prefix = "";public RedisTokenStore(RedisConnectionFactory connectionFactory) {this.connectionFactory = connectionFactory;}public void setAuthenticationKeyGenerator(AuthenticationKeyGenerator authenticationKeyGenerator) {this.authenticationKeyGenerator = authenticationKeyGenerator;}public void setSerializationStrategy(RedisTokenStoreSerializationStrategy serializationStrategy) {this.serializationStrategy = serializationStrategy;}public void setPrefix(String prefix) {this.prefix = prefix;}private RedisConnection getConnection() {return this.connectionFactory.getConnection();}private byte[] serialize(Object object) {return this.serializationStrategy.serialize(object);}private byte[] serializeKey(String object) {return this.serialize(this.prefix + object);}private OAuth2AccessToken deserializeAccessToken(byte[] bytes) {return (OAuth2AccessToken)this.serializationStrategy.deserialize(bytes, OAuth2AccessToken.class);}private OAuth2Authentication deserializeAuthentication(byte[] bytes) {return (OAuth2Authentication)this.serializationStrategy.deserialize(bytes, OAuth2Authentication.class);}private OAuth2RefreshToken deserializeRefreshToken(byte[] bytes) {return (OAuth2RefreshToken)this.serializationStrategy.deserialize(bytes, OAuth2RefreshToken.class);}private byte[] serialize(String string) {return this.serializationStrategy.serialize(string);}private String deserializeString(byte[] bytes) {return this.serializationStrategy.deserializeString(bytes);}@Overridepublic OAuth2AccessToken getAccessToken(OAuth2Authentication authentication) {String key = this.authenticationKeyGenerator.extractKey(authentication);byte[] serializedKey = this.serializeKey(AUTH_TO_ACCESS + key);byte[] bytes = null;RedisConnection conn = this.getConnection();try {bytes = conn.get(serializedKey);} finally {conn.close();}OAuth2AccessToken accessToken = this.deserializeAccessToken(bytes);if (accessToken != null) {OAuth2Authentication storedAuthentication = this.readAuthentication(accessToken.getValue());if (storedAuthentication == null || !key.equals(this.authenticationKeyGenerator.extractKey(storedAuthentication))) {this.storeAccessToken(accessToken, authentication);}}return accessToken;}@Overridepublic OAuth2Authentication readAuthentication(OAuth2AccessToken token) {return this.readAuthentication(token.getValue());}@Overridepublic OAuth2Authentication readAuthentication(String token) {byte[] bytes = null;RedisConnection conn = this.getConnection();try {bytes = conn.get(this.serializeKey("auth:" + token));} finally {conn.close();}OAuth2Authentication auth = this.deserializeAuthentication(bytes);return auth;}@Overridepublic OAuth2Authentication readAuthenticationForRefreshToken(OAuth2RefreshToken token) {return this.readAuthenticationForRefreshToken(token.getValue());}public OAuth2Authentication readAuthenticationForRefreshToken(String token) {RedisConnection conn = getConnection();try {byte[] bytes = conn.get(serializeKey(REFRESH_AUTH + token));OAuth2Authentication auth = deserializeAuthentication(bytes);return auth;} finally {conn.close();}}@Overridepublic void storeAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) {byte[] serializedAccessToken = serialize(token);byte[] serializedAuth = serialize(authentication);byte[] accessKey = serializeKey(ACCESS + token.getValue());byte[] authKey = serializeKey(AUTH + token.getValue());byte[] authToAccessKey = serializeKey(AUTH_TO_ACCESS + authenticationKeyGenerator.extractKey(authentication));byte[] approvalKey = serializeKey(UNAME_TO_ACCESS + getApprovalKey(authentication));byte[] clientId = serializeKey(CLIENT_ID_TO_ACCESS + authentication.getOAuth2Request().getClientId());RedisConnection conn = getConnection();try {conn.openPipeline();conn.stringCommands().set(accessKey, serializedAccessToken);conn.stringCommands().set(authKey, serializedAuth);conn.stringCommands().set(authToAccessKey, serializedAccessToken);if (!authentication.isClientOnly()) {conn.rPush(approvalKey, serializedAccessToken);}conn.rPush(clientId, serializedAccessToken);if (token.getExpiration() != null) {int seconds = token.getExpiresIn();conn.expire(accessKey, seconds);conn.expire(authKey, seconds);conn.expire(authToAccessKey, seconds);conn.expire(clientId, seconds);conn.expire(approvalKey, seconds);}OAuth2RefreshToken refreshToken = token.getRefreshToken();if (refreshToken != null && refreshToken.getValue() != null) {byte[] refresh = serialize(token.getRefreshToken().getValue());byte[] auth = serialize(token.getValue());byte[] refreshToAccessKey = serializeKey(REFRESH_TO_ACCESS + token.getRefreshToken().getValue());conn.stringCommands().set(refreshToAccessKey, auth);byte[] accessToRefreshKey = serializeKey(ACCESS_TO_REFRESH + token.getValue());conn.stringCommands().set(accessToRefreshKey, refresh);if (refreshToken instanceof ExpiringOAuth2RefreshToken) {ExpiringOAuth2RefreshToken expiringRefreshToken = (ExpiringOAuth2RefreshToken) refreshToken;Date expiration = expiringRefreshToken.getExpiration();if (expiration != null) {int seconds = Long.valueOf((expiration.getTime() - System.currentTimeMillis()) / 1000L).intValue();conn.expire(refreshToAccessKey, seconds);conn.expire(accessToRefreshKey, seconds);}}}conn.closePipeline();} finally {conn.close();}}private static String getApprovalKey(OAuth2Authentication authentication) {String userName = authentication.getUserAuthentication() == null ? "": authentication.getUserAuthentication().getName();return getApprovalKey(authentication.getOAuth2Request().getClientId(), userName);}private static String getApprovalKey(String clientId, String userName) {return clientId + (userName == null ? "" : ":" + userName);}@Overridepublic void removeAccessToken(OAuth2AccessToken accessToken) {this.removeAccessToken(accessToken.getValue());}@Overridepublic OAuth2AccessToken readAccessToken(String tokenValue) {byte[] key = serializeKey(ACCESS + tokenValue);byte[] bytes = null;RedisConnection conn = getConnection();try {bytes = conn.get(key);} finally {conn.close();}OAuth2AccessToken accessToken = deserializeAccessToken(bytes);return accessToken;}public void removeAccessToken(String tokenValue) {byte[] accessKey = serializeKey(ACCESS + tokenValue);byte[] authKey = serializeKey(AUTH + tokenValue);byte[] accessToRefreshKey = serializeKey(ACCESS_TO_REFRESH + tokenValue);RedisConnection conn = getConnection();try {conn.openPipeline();conn.get(accessKey);conn.get(authKey);conn.del(accessKey);conn.del(accessToRefreshKey);// Don't remove the refresh token - it's up to the caller to do thatconn.del(authKey);List<Object> results = conn.closePipeline();byte[] access = (byte[]) results.get(0);byte[] auth = (byte[]) results.get(1);OAuth2Authentication authentication = deserializeAuthentication(auth);if (authentication != null) {String key = authenticationKeyGenerator.extractKey(authentication);byte[] authToAccessKey = serializeKey(AUTH_TO_ACCESS + key);byte[] unameKey = serializeKey(UNAME_TO_ACCESS + getApprovalKey(authentication));byte[] clientId = serializeKey(CLIENT_ID_TO_ACCESS + authentication.getOAuth2Request().getClientId());conn.openPipeline();conn.del(authToAccessKey);conn.lRem(unameKey, 1, access);conn.lRem(clientId, 1, access);conn.del(serialize(ACCESS + key));conn.closePipeline();}} finally {conn.close();}}@Overridepublic void storeRefreshToken(OAuth2RefreshToken refreshToken, OAuth2Authentication authentication) {byte[] refreshKey = serializeKey(REFRESH + refreshToken.getValue());byte[] refreshAuthKey = serializeKey(REFRESH_AUTH + refreshToken.getValue());byte[] serializedRefreshToken = serialize(refreshToken);RedisConnection conn = getConnection();try {conn.openPipeline();conn.stringCommands().set(refreshKey, serializedRefreshToken);conn.stringCommands().set(refreshAuthKey, serialize(authentication));if (refreshToken instanceof ExpiringOAuth2RefreshToken) {ExpiringOAuth2RefreshToken expiringRefreshToken = (ExpiringOAuth2RefreshToken) refreshToken;Date expiration = expiringRefreshToken.getExpiration();if (expiration != null) {int seconds = Long.valueOf((expiration.getTime() - System.currentTimeMillis()) / 1000L).intValue();conn.expire(refreshKey, seconds);conn.expire(refreshAuthKey, seconds);}}conn.closePipeline();} finally {conn.close();}}@Overridepublic OAuth2RefreshToken readRefreshToken(String tokenValue) {byte[] key = serializeKey(REFRESH + tokenValue);byte[] bytes = null;RedisConnection conn = getConnection();try {bytes = conn.get(key);} finally {conn.close();}OAuth2RefreshToken refreshToken = deserializeRefreshToken(bytes);return refreshToken;}@Overridepublic void removeRefreshToken(OAuth2RefreshToken refreshToken) {this.removeRefreshToken(refreshToken.getValue());}public void removeRefreshToken(String tokenValue) {byte[] refreshKey = serializeKey(REFRESH + tokenValue);byte[] refreshAuthKey = serializeKey(REFRESH_AUTH + tokenValue);byte[] refresh2AccessKey = serializeKey(REFRESH_TO_ACCESS + tokenValue);byte[] access2RefreshKey = serializeKey(ACCESS_TO_REFRESH + tokenValue);RedisConnection conn = getConnection();try {conn.openPipeline();conn.del(refreshKey);conn.del(refreshAuthKey);conn.del(refresh2AccessKey);conn.del(access2RefreshKey);conn.closePipeline();} finally {conn.close();}}@Overridepublic void removeAccessTokenUsingRefreshToken(OAuth2RefreshToken refreshToken) {this.removeAccessTokenUsingRefreshToken(refreshToken.getValue());}private void removeAccessTokenUsingRefreshToken(String refreshToken) {byte[] key = serializeKey(REFRESH_TO_ACCESS + refreshToken);List<Object> results = null;RedisConnection conn = getConnection();try {conn.openPipeline();conn.get(key);conn.del(key);results = conn.closePipeline();} finally {conn.close();}if (results == null) {return;}byte[] bytes = (byte[]) results.get(0);String accessToken = deserializeString(bytes);if (accessToken != null) {removeAccessToken(accessToken);}}@Overridepublic Collection<OAuth2AccessToken> findTokensByClientIdAndUserName(String clientId, String userName) {byte[] approvalKey = serializeKey(UNAME_TO_ACCESS + getApprovalKey(clientId, userName));List<byte[]> byteList = null;RedisConnection conn = getConnection();try {byteList = conn.lRange(approvalKey, 0, -1);} finally {conn.close();}if (byteList == null || byteList.size() == 0) {return Collections.<OAuth2AccessToken> emptySet();}List<OAuth2AccessToken> accessTokens = new ArrayList<OAuth2AccessToken>(byteList.size());for (byte[] bytes : byteList) {OAuth2AccessToken accessToken = deserializeAccessToken(bytes);accessTokens.add(accessToken);}return Collections.<OAuth2AccessToken> unmodifiableCollection(accessTokens);}@Overridepublic Collection<OAuth2AccessToken> findTokensByClientId(String clientId) {byte[] key = serializeKey(CLIENT_ID_TO_ACCESS + clientId);List<byte[]> byteList = null;RedisConnection conn = getConnection();try {byteList = conn.lRange(key, 0, -1);} finally {conn.close();}if (byteList == null || byteList.size() == 0) {return Collections.<OAuth2AccessToken> emptySet();}List<OAuth2AccessToken> accessTokens = new ArrayList<OAuth2AccessToken>(byteList.size());for (byte[] bytes : byteList) {OAuth2AccessToken accessToken = deserializeAccessToken(bytes);accessTokens.add(accessToken);}return Collections.<OAuth2AccessToken> unmodifiableCollection(accessTokens);}
}

SecurityConfig类

package com.liuhao.demo.config.security;
import com.alibaba.fastjson.JSON;
import com.liuhao.demo.service.impl.TUserServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
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.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;/*** 〈security配置〉** @author Curise* @create 2018/12/13* @since 1.0.0*/
@Configuration
@EnableWebSecurity
@Order(2)
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate TUserServiceImpl userDetailService;@Autowiredprivate PasswordEncoder passwordEncoder;/*** 过滤 oauth 所有的请求,其他请求进行拦截* @param http* @throws Exception*/@Overrideprotected void configure(HttpSecurity http) throws Exception {//过滤 oauth 请求http.requestMatchers().antMatchers("/oauth/**").and().authorizeRequests().antMatchers("/oauth/**").authenticated().and().csrf().disable();}/*** 配置 校验用户名和密码的 还有加密方式* @param auth* @throws Exception*/@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(userDetailService).passwordEncoder(passwordEncoder);}/*** 不定义没有password grant_type,密码模式需要AuthenticationManager支持** @return* @throws Exception*/@Override@Beanpublic AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean();}
}

TUserServiceImpl 类

package com.liuhao.demo.service.impl;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.liuhao.demo.entity.TUser;
import com.liuhao.demo.mapper.TUserMapper;
import com.liuhao.demo.service.IUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
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;/*** <p>*  服务实现类* </p>** @author liuhao* @since 2020-05-21*/
@Service
@Slf4j
public class TUserServiceImpl extends ServiceImpl<TUserMapper, TUser> implements IUserService, UserDetailsService {@Overridepublic UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {log.info("用户进行认证的用户名为:{}",s);QueryWrapper<TUser> objectQueryWrapper = new QueryWrapper<>();objectQueryWrapper.eq("user_name",s);TUser tUser1 = this.baseMapper.selectOne(objectQueryWrapper);if (tUser1==null){throw  new UsernameNotFoundException("用户名不存在");}return new User(s,tUser1.getUserPassword(), AuthorityUtils.createAuthorityList("admin"));}
}

JyShopTestApplication类

package com.liuhao.demo;import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.Bean;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;@SpringBootApplication
@EnableDiscoveryClient
@MapperScan(basePackages = "com.liuhao.demo.mapper")
public class JyShopTestApplication {public static void main(String[] args) {SpringApplication.run(JyShopTestApplication.class,args);}@Beanpublic PasswordEncoder passwordEncoder(){return new BCryptPasswordEncoder();}
}

bootstrap.properties配置文件

spring.cloud.nacos.config.server-addr=127.0.0.1:8848
spring.application.name=jyshop
spring.profiles.active=dev
spring.cloud.nacos.config.file-extension=properties

application.properties配置文件

使用nacos注册中心 该配置可置于nacos配置中心

spring.application.name=jyshop-test
server.port=8090
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
#数据源
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/1707a?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
mybatis-plus.mapper-locations=classpath:xml/*.xml

使用postMan进去数据请求 body为返回效果

集成SpringSecurity和Oauth2的授权码认证相关推荐

  1. OAuth2.0授权码认证流程介绍

    Oauth2授权模式 Oauth2授权模式 Oauth2有以下授权模式: 1.授权码模式(Authorization Code) 2.隐式授权模式(Implicit)  3.密码模式(Resource ...

  2. OAuth2.0 授权码认证方式使用流程

    第一步:获取授权码 /oauth/authorize?client_id=c1&response_type=code&scope=all&redirect_uri=http:/ ...

  3. 搭建认证服务器 - Spring Security Oauth2.0 集成 Jwt 之 【授权码认证流程】 总结

    在搭建介绍流程之前,确保您已经搭建了一个 Eureka 注册中心,因为没有注册中心的话会报错(也有可能我搭建的认证服务器是我项目的一个子模块的原因):Request execution error. ...

  4. OAuth2.0授权码模式原理与实战

    OAuth2.0是目前比较流行的一种开源授权协议,可以用来授权第三方应用,允许在不将用户名和密码提供给第三方应用的情况下获取一定的用户资源,目前很多网站或APP基于微信或QQ的第三方登录方式都是基于O ...

  5. OAuth2.0授权码模式实战

    OAuth2.0是目前比较流行的一种开源授权协议,可以用来授权第三方应用,允许在不将用户名和密码提供给第三方应用的情况下获取一定的用户资源,目前很多网站或APP基于微信或QQ的第三方登录方式都是基于O ...

  6. java 32位授权码_Java实现OAuth2.0授权码方式

    Java实现OAuth2.0授权码方式 前面介绍了OAuth2.0和授权方式,可以参考以下文章: 今天就用Java来验证OAuth2.0授权方式的授权码式,我们Spring Cloud的OAuth来实 ...

  7. OAuth2.0授权码模式学习

    OAuth2.0授权码模式学习 四种授权方式 1,授权码模式 2,简化模式 3,密码模式 4,客户端模式 授权码模式 四种授权模式中最完成,最严密的授权. (1)用户访问客户端,后者将前者导入认证服务 ...

  8. java.securti_springboot集成springsecurity 使用OAUTH2做权限管理的教程

    Spring Security OAuth2 主要配置,注意application.yml最后的配置resource filter顺序配置,不然会能获取token但是访问一直 没有权限 WebSecu ...

  9. oauth2.0授权码模式详解

    Python微信订餐小程序课程视频 https://edu.csdn.net/course/detail/36074 Python实战量化交易理财系统 https://edu.csdn.net/cou ...

最新文章

  1. C#(WPF)去除事件中注册的事件处理方法!
  2. 下载Ext JS 5.1 gpl版本的方法
  3. 一起谈.NET技术,Expression Blend中文教程 - 开篇
  4. linux抓post命令,Linux 使用curl发起post请求的4个常用方式
  5. 【图像处理】——Python+opencv实现二值图像的轮廓边界跟踪以及轮廓面积周长的求解(findcontours函数和contourArea函数)
  6. 32位python和64位python区别_python32位和64位有什么区别
  7. Failedto load class org.slf4j.impl.StaticLogger...
  8. 数据可视化最容易被人忽略的四大误区,怪不得我的报告总被老板骂
  9. 大数据安全分析需要关注哪些问题
  10. 【代码实现和训练】OCR技术——引入了Attention机制的crnn的印刷体汉字识别
  11. L19.linux命令每日一练 -- 第三章 文件过滤及内容编辑处理命令 -- tailf和cut命令
  12. SSM社区医院卫生所病人患者随访信息管理javaweb网站系统设计与实现
  13. 基于FPGA的循迹小车,控制器:Xilinx-Ego1
  14. js实现oss批量下载文件_远程URL文件批量下载打包的方法
  15. win10无法装载重装系统iso文件_win10镜像不能安装系统如何解决_win10镜像无法安装处理方法...
  16. 能量英语(一)之激情英语
  17. 计算机东北大学与兰州大学哪个好,东北大学和兰州大学如何选择?上哪个比较好?...
  18. 手机安全卫士的一些总结
  19. 安全产品的核心逻辑-IPS/IDS
  20. 关于数据库系统的学习

热门文章

  1. Amazon EKS 新功能上线——助你降低配置和管理复杂度
  2. ARM ADDS和ADCS的区别
  3. 利用日照时数计算太阳辐射
  4. 学习微积分60年有感(IV)
  5. POSCMS标签笔记
  6. LinuxC语言 目录操作
  7. 聊一聊我在 B 站自学 Java 的经历吧
  8. rdma-轮询常用cq函数。
  9. 浏览器批量打开网站在线工具
  10. SwitchResX for Mac 屏幕分辨率修改工具