鉴权业务层

AuthorizationServerConfig类:
package com.changgou.oauth.config;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.bootstrap.encrypt.KeyProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
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.ClientDetailsService;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
import org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter;
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.oauth2.provider.token.store.KeyStoreKeyFactory;import javax.annotation.Resource;
import javax.sql.DataSource;
import java.security.KeyPair;@Configuration
@EnableAuthorizationServer
class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {//数据源,用于从数据库获取数据进行认证操作,测试可以从内存中获取@Autowiredprivate DataSource dataSource;//jwt令牌转换器@Autowiredprivate JwtAccessTokenConverter jwtAccessTokenConverter;//SpringSecurity 用户自定义授权认证类@AutowiredUserDetailsService userDetailsService;//授权认证管理器@AutowiredAuthenticationManager authenticationManager;//令牌持久化存储接口@AutowiredTokenStore tokenStore;@Autowiredprivate CustomUserAuthenticationConverter customUserAuthenticationConverter;/**** 客户端信息配置* @param clients* @throws Exception*/@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {clients.jdbc(dataSource).clients(clientDetails());}/**** 授权服务器端点配置* @param endpoints* @throws Exception*/@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {endpoints.accessTokenConverter(jwtAccessTokenConverter).authenticationManager(authenticationManager)//认证管理器.tokenStore(tokenStore)                       //令牌存储.userDetailsService(userDetailsService);     //用户信息service}/**** 授权服务器的安全配置* @param oauthServer* @throws Exception*/@Overridepublic void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {oauthServer.allowFormAuthenticationForClients().passwordEncoder(new BCryptPasswordEncoder()).tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");}//读取密钥的配置@Bean("keyProp")public KeyProperties keyProperties(){return new KeyProperties();}@Resource(name = "keyProp")private KeyProperties keyProperties;//客户端配置@Beanpublic ClientDetailsService clientDetails() {return new JdbcClientDetailsService(dataSource);}@Bean@Autowiredpublic TokenStore tokenStore(JwtAccessTokenConverter jwtAccessTokenConverter) {return new JwtTokenStore(jwtAccessTokenConverter);}/***** JWT令牌转换器* @param customUserAuthenticationConverter* @return*/@Beanpublic JwtAccessTokenConverter jwtAccessTokenConverter(CustomUserAuthenticationConverter customUserAuthenticationConverter) {JwtAccessTokenConverter converter = new JwtAccessTokenConverter();KeyPair keyPair = new KeyStoreKeyFactory(keyProperties.getKeyStore().getLocation(),                          //证书路径 changgou.jkskeyProperties.getKeyStore().getSecret().toCharArray())              //证书秘钥 changgouapp.getKeyPair(keyProperties.getKeyStore().getAlias(),                     //证书别名 changgoukeyProperties.getKeyStore().getPassword().toCharArray());   //证书密码 changgouconverter.setKeyPair(keyPair);//配置自定义的CustomUserAuthenticationConverterDefaultAccessTokenConverter accessTokenConverter = (DefaultAccessTokenConverter) converter.getAccessTokenConverter();accessTokenConverter.setUserTokenConverter(customUserAuthenticationConverter);return converter;}
}
CustomUserAuthenticationConverter类
package com.changgou.oauth.config;import com.changgou.oauth.util.UserJwt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.oauth2.provider.token.DefaultUserAuthenticationConverter;
import org.springframework.stereotype.Component;import java.util.LinkedHashMap;
import java.util.Map;@Component
public class CustomUserAuthenticationConverter extends DefaultUserAuthenticationConverter {@AutowiredUserDetailsService userDetailsService;@Overridepublic Map<String, ?> convertUserAuthentication(Authentication authentication) {LinkedHashMap response = new LinkedHashMap();String name = authentication.getName();response.put("username", name);Object principal = authentication.getPrincipal();UserJwt userJwt = null;if(principal instanceof  UserJwt){userJwt = (UserJwt) principal;}else{//refresh_token默认不去调用userdetailService获取用户信息,这里我们手动去调用,得到 UserJwtUserDetails userDetails = userDetailsService.loadUserByUsername(name);userJwt = (UserJwt) userDetails;}response.put("name", userJwt.getName());response.put("id", userJwt.getId());if (authentication.getAuthorities() != null && !authentication.getAuthorities().isEmpty()) {response.put("authorities", AuthorityUtils.authorityListToSet(authentication.getAuthorities()));}return response;}}
UserDetailsServiceImpl类
package com.changgou.oauth.config;import com.changgou.oauth.util.UserJwt;
import com.changgou.user.feign.UserFeign;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
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.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;/****** 自定义授权认证类*/
@Service
public class UserDetailsServiceImpl implements UserDetailsService {@AutowiredClientDetailsService clientDetailsService;@Autowiredprivate UserFeign userFeign;/***** 自定义授权认证* @param username* @return* @throws UsernameNotFoundException*/@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {//取出身份,如果身份为空说明没有认证Authentication authentication = SecurityContextHolder.getContext().getAuthentication();//没有认证统一采用httpbasic认证,httpbasic中存储了client_id和client_secret,开始认证client_id和client_secretif(authentication==null){ClientDetails clientDetails = clientDetailsService.loadClientByClientId(username);if(clientDetails!=null){//秘钥String clientSecret = clientDetails.getClientSecret();//静态方式//return new User(username,new BCryptPasswordEncoder().encode(clientSecret), AuthorityUtils.commaSeparatedStringToAuthorityList(""));//数据库查找方式return new User(username,clientSecret, AuthorityUtils.commaSeparatedStringToAuthorityList(""));}}if (StringUtils.isEmpty(username)) {return null;}//根据用户名查询用户信息//String pwd = new BCryptPasswordEncoder().encode("123456");com.changgou.user.pojo.User userInfo = userFeign.findUserInfo(username);//创建User对象String permissions = "goods_list,seckill_list";UserJwt userDetails = new UserJwt(username,userInfo.getPassword(),AuthorityUtils.commaSeparatedStringToAuthorityList(permissions));return userDetails;}
}
WebSecurityConfig类
package com.changgou.oauth.config;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.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;@Configuration
@EnableWebSecurity
@Order(-1)
class WebSecurityConfig extends WebSecurityConfigurerAdapter {/**** 忽略安全拦截的URL* @param web* @throws Exception*/@Overridepublic void configure(WebSecurity web) throws Exception {web.ignoring().antMatchers("/oauth/login","/oauth/logout","/oauth/toLogin","/login.html","/css/**","/data/**","/fonts/**","/img/**","/js/**");}/**** 创建授权管理认证对象* @return* @throws Exception*/@Bean@Overridepublic AuthenticationManager authenticationManagerBean() throws Exception {AuthenticationManager manager = super.authenticationManagerBean();return manager;}/**** 采用BCryptPasswordEncoder对密码进行编码* @return*/@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}/****** @param http* @throws Exception*/@Overridepublic void configure(HttpSecurity http) throws Exception {http.csrf().disable().httpBasic()        //启用Http基本身份验证.and().formLogin()       //启用表单身份验证.and().authorizeRequests()    //限制基于Request请求访问.anyRequest().authenticated();       //其他请求都需要经过验证http.formLogin().loginPage("/oauth/toLogin").loginProcessingUrl("/oauth/login");}
}
AuthToken工具类
package com.changgou.oauth.util;import java.io.Serializable;public class AuthToken implements Serializable{//令牌信息String accessToken;//刷新token(refresh_token)String refreshToken;//jwt短令牌String jti;public String getAccessToken() {return accessToken;}public void setAccessToken(String accessToken) {this.accessToken = accessToken;}public String getRefreshToken() {return refreshToken;}public void setRefreshToken(String refreshToken) {this.refreshToken = refreshToken;}public String getJti() {return jti;}public void setJti(String jti) {this.jti = jti;}
}
CookieUtil工具类
package com.changgou.oauth.util;import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;/*** Created by admin on 2018/3/18.*/
public class CookieUtil {/*** 设置cookie** @param response* @param name     cookie名字* @param value    cookie值* @param maxAge   cookie生命周期 以秒为单位*/public static void addCookie(HttpServletResponse response, String domain, String path, String name,String value, int maxAge, boolean httpOnly) {Cookie cookie = new Cookie(name, value);cookie.setDomain(domain);cookie.setPath(path);cookie.setMaxAge(maxAge);cookie.setHttpOnly(httpOnly);response.addCookie(cookie);}/*** 根据cookie名称读取cookie* @param request* @return map<cookieName,cookieValue>*/public static Map<String,String> readCookie(HttpServletRequest request, String ... cookieNames) {Map<String,String> cookieMap = new HashMap<String,String>();Cookie[] cookies = request.getCookies();if (cookies != null) {for (Cookie cookie : cookies) {String cookieName = cookie.getName();String cookieValue = cookie.getValue();for(int i=0;i<cookieNames.length;i++){if(cookieNames[i].equals(cookieName)){cookieMap.put(cookieName,cookieValue);}}}}return cookieMap;}
}
UserJwt工具类
package com.changgou.oauth.util;import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;import java.util.Collection;public class UserJwt extends User {private String id;    //用户IDprivate String name;  //用户名字public UserJwt(String username, String password, Collection<? extends GrantedAuthority> authorities) {super(username, password, authorities);}public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}
}

公钥与私钥如何生成请参考RSA公钥和秘钥生成方法_lppklm的专栏-CSDN博客在liunx环境中装上open_ssl(这是前提)1.openssl genrsa -des3 -out prikey.pem 1024  #生成rsa密钥   Enter pass phrase for prikey.pem: xxx   Verifying - Enter pass phrase for prikey.pem: xxx2.openssl rsa -in prhttps://blog.csdn.net/lppklm/article/details/45225137

以上是linux系统中生成,对linux不太友好,有机会写一篇window下生成的

不忘记导入spring security依赖还有Oauth2.0的依赖

<dependencies><!--查询数据库数据--><dependency><groupId>com.changgou</groupId><artifactId>changgou_common_db</artifactId><version>1.0-SNAPSHOT</version></dependency><dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-data</artifactId></dependency><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-actuator</artifactId></dependency><dependency><groupId>com.changgou</groupId><artifactId>changgou_service_user_api</artifactId><version>1.0-SNAPSHOT</version></dependency><!--thymeleaf--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency></dependencies>

ymlpei配置文件

server:port: 9200
spring:application:name: user-authredis:host: 192.168.200.128port: 6379password:jedis:pool:max-active: 8max-idle: 8min-idle: 0datasource:driver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://192.168.200.128:3306/changgou_user?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true&serverTimezone=UTCusername: rootpassword: rootmain:allow-bean-definition-overriding: true
eureka:instance:prefer-ip-address: trueclient:service-url:defaultZone: http://127.0.0.1:6868/eureka
auth:ttl: 3600  #token存储到redis的过期时间clientId: changgouclientSecret: changgoucookieDomain: localhostcookieMaxAge: -1
encrypt:key-store:location: classpath:/changgou.jkssecret: changgoualias: changgoupassword: changgou

用私钥生成token令牌测试

package com.changgou.oauth;import com.alibaba.fastjson.JSON;
import org.junit.Test;
import org.springframework.core.io.ClassPathResource;
import org.springframework.security.jwt.Jwt;
import org.springframework.security.jwt.JwtHelper;
import org.springframework.security.jwt.crypto.sign.RsaSigner;
import org.springframework.security.rsa.crypto.KeyStoreKeyFactory;import java.security.KeyPair;
import java.security.interfaces.RSAPrivateKey;
import java.util.HashMap;
import java.util.Map;public class CreateJWTTest {@Testpublic void createJWT(){//基于私钥生成jwt//1. 创建一个秘钥工厂//1: 指定私钥的位置ClassPathResource classPathResource = new ClassPathResource("changgou.jks");//2: 指定秘钥库的密码String keyPass = "changgou";KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(classPathResource,keyPass.toCharArray());//2. 基于工厂获取私钥String alias = "changgou";String password = "changgou";KeyPair keyPair = keyStoreKeyFactory.getKeyPair(alias, password.toCharArray());//将当前的私钥转换为rsa私钥RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();//3.生成jwtMap<String,String> map = new HashMap();map.put("company","heima");map.put("address","beijing");Jwt jwt = JwtHelper.encode(JSON.toJSONString(map), new RsaSigner(rsaPrivateKey));String jwtEncoded = jwt.getEncoded();System.out.println(jwtEncoded);}
}

用公钥解析令牌测试

package com.changgou.oauth;import org.junit.Test;
import org.springframework.security.jwt.Jwt;
import org.springframework.security.jwt.JwtHelper;
import org.springframework.security.jwt.crypto.sign.RsaVerifier;public class ParseJwtTest {@Testpublic void parseJwt(){//基于公钥去解析jwtString jwt ="eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhZGRyZXNzIjoiYmVpamluZyIsImNvbXBhbnkiOiJoZWltYSJ9.cjZNz8G0m4noNYN2VM1SH3ujAtbHElW5Vtbadb0NDI0cjM1DaAXzMA53Qbj4pmVQPl_IfSKqUEXbLxowdRa5NHR43laFsR0kzGbJiTINfSVSroSslYpDdEVwCeAF_a7I-R819YTj4p6sjuYKXbzXpeZQErczFbWWWGR2_U44xH6u1ejRNv8PikFiuzNw-muL7zUJkvqeSJzbEMnQdZMbfvZp4LtSI6B4G_PqpdNXkv19-juxAh99VgJInH_ItF0y5IBOxofA7gRebCZmU8L57gO9ohf2L00D95kis_Ji8lmA1ptLIfXqO_qLVvLBUNH-VtgjGAF0-0pyB-5jlbHP7w";String publicKey ="-----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvFsEiaLvij9C1Mz+oyAmt47whAaRkRu/8kePM+X8760UGU0RMwGti6Z9y3LQ0RvK6I0brXmbGB/RsN38PVnhcP8ZfxGUH26kX0RK+tlrxcrG+HkPYOH4XPAL8Q1lu1n9x3tLcIPxq8ZZtuIyKYEmoLKyMsvTviG5flTpDprT25unWgE4md1kthRWXOnfWHATVY7Y/r4obiOL1mS5bEa/iNKotQNnvIAKtjBM4RlIDWMa6dmz+lHtLtqDD2LF1qwoiSIHI75LQZ/CNYaHCfZSxtOydpNKq8eb1/PGiLNolD4La2zf0/1dlcr5mkesV570NxRmU1tFm8Zd3MZlZmyv9QIDAQAB-----END PUBLIC KEY-----";Jwt token = JwtHelper.decodeAndVerify(jwt, new RsaVerifier(publicKey));String claims = token.getClaims();System.out.println(claims);}
}

获取token令牌测试

package com.changgou.oauth;import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.Base64Utils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.DefaultResponseErrorHandler;
import org.springframework.web.client.RestTemplate;import java.io.IOException;
import java.net.URI;
import java.util.Map;@SpringBootTest
@RunWith(SpringRunner.class)
public class ApplyTokenTest {@Autowiredprivate RestTemplate restTemplate;@Autowiredprivate LoadBalancerClient loadBalancerClient;@Testpublic void applyToken(){//构建请求地址  http://localhost:9200/oauth/tokenServiceInstance serviceInstance = loadBalancerClient.choose("user-auth");// http://localhost:9200URI uri = serviceInstance.getUri();// http://localhost:9200/oauth/tokenString url =uri+"/oauth/token";// 封装请求参数 body , headersMultiValueMap<String, String> body = new LinkedMultiValueMap<>();body.add("grant_type","password");body.add("username","itheima");body.add("password","itheima");MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();headers.add("Authorization",this.getHttpBasic("changgou","changgou"));HttpEntity<MultiValueMap<String,String>> requestEntity = new HttpEntity<>(body,headers);//当后端出现了401,400.后端不对着两个异常编码进行处理,而是直接返回给前端restTemplate.setErrorHandler(new DefaultResponseErrorHandler(){@Overridepublic void handleError(ClientHttpResponse response) throws IOException {if (response.getRawStatusCode()!=400 && response.getRawStatusCode() != 401){super.handleError(response);}}});//发送请求ResponseEntity<Map> responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity, Map.class);Map map = responseEntity.getBody();System.out.println(map);}private String getHttpBasic(String clientId, String clientSecret) {String value =clientId+":"+clientSecret;byte[] encode = Base64Utils.encode(value.getBytes());//Basic Y2hhbmdnb3U6Y2hhbmdnb3U=return "Basic "+new String(encode);}
}

在需要鉴权的服务的内容

添加Oauth2.0的依赖.在springBoot工程中依赖具有传递性,所以同时为导入spring security和两者整合依赖

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-oauth2</artifactId></dependency>

把可以解密的公钥放入资源目录夹

添加解密服务配置类ResourceServerConfig

package com.changgou.user.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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;
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 java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.stream.Collectors;@Configuration
@EnableResourceServer
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)//激活方法上的PreAuthorize注解
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {//公钥private static final String PUBLIC_KEY = "public.key";/**** 定义JwtTokenStore* @param jwtAccessTokenConverter* @return*/@Beanpublic TokenStore tokenStore(JwtAccessTokenConverter jwtAccessTokenConverter) {return new JwtTokenStore(jwtAccessTokenConverter);}/**** 定义JJwtAccessTokenConverter* @return*/@Beanpublic JwtAccessTokenConverter jwtAccessTokenConverter() {JwtAccessTokenConverter converter = new JwtAccessTokenConverter();converter.setVerifierKey(getPubKey());return converter;}/*** 获取非对称加密公钥 Key* @return 公钥 Key*/private String getPubKey() {Resource resource = new ClassPathResource(PUBLIC_KEY);try {InputStreamReader inputStreamReader = new InputStreamReader(resource.getInputStream());BufferedReader br = new BufferedReader(inputStreamReader);return br.lines().collect(Collectors.joining("\n"));} catch (IOException ioe) {return null;}}/**** Http安全配置,对每个到达系统的http请求链接进行校验* @param http* @throws Exception*/@Overridepublic void configure(HttpSecurity http) throws Exception {//所有请求必须认证通过http.authorizeRequests()//下边的路径放行.antMatchers("/user/add","/user/load/**"). //配置地址放行permitAll().anyRequest().authenticated();    //其他地址需要认证授权}
}

接下来就是登录的业务逻辑

具体实现业务逻辑如下

就不赘述

鉴权登录可以给个参考

登录AuthServiceImpl业务层
package com.changgou.oauth.service.impl;import com.changgou.oauth.service.AuthService;
import com.changgou.oauth.util.AuthToken;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Service;
import org.springframework.util.Base64Utils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.DefaultResponseErrorHandler;
import org.springframework.web.client.RestTemplate;import java.io.IOException;
import java.net.URI;
import java.util.Map;
import java.util.concurrent.TimeUnit;@Service
public class AuthServiceImpl implements AuthService {@Autowiredprivate RestTemplate restTemplate;@Autowiredprivate LoadBalancerClient loadBalancerClient;@Autowiredprivate StringRedisTemplate stringRedisTemplate;@Value("${auth.ttl}")private long ttl;/*** 申请令牌* @param username* @param password* @param clientId* @param clientSecret* @return*/@Overridepublic AuthToken login(String username, String password, String clientId, String clientSecret) {ServiceInstance serviceInstance = loadBalancerClient.choose("user-auth");URI uri = serviceInstance.getUri();String url = uri+"/oauth/token";MultiValueMap<String, String> body = new LinkedMultiValueMap<>();body.add("grant_type","password");body.add("username",username);body.add("password",password);MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();headers.add("Authorization",this.getHttpBasic(clientId,clientSecret));HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(body,headers);restTemplate.setErrorHandler(new DefaultResponseErrorHandler(){@Overridepublic void handleError(ClientHttpResponse response) throws IOException {if (response.getRawStatusCode()!=400 && response.getRawStatusCode()!=401){super.handleError(response);}}});ResponseEntity<Map> responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity, Map.class);Map map = responseEntity.getBody();if (map==null || map.get("access_token")==null || map.get("refresh_token")==null || map.get("jti")==null){throw new RuntimeException("申请令牌失败");}AuthToken authToken = new AuthToken();authToken.setAccessToken((String) map.get("access_token"));authToken.setRefreshToken((String) map.get("refresh_token"));authToken.setJti((String) map.get("jti"));stringRedisTemplate.boundValueOps(authToken.getJti()).set(authToken.getAccessToken(),ttl, TimeUnit.SECONDS);return authToken;}private String getHttpBasic(String clientId, String clientSecret) {String value = clientId+":"+clientSecret;byte[] encode = Base64Utils.encode(value.getBytes());return "Basic "+new String(encode);}
}

登录的表现层

package com.changgou.oauth.controller_20190929_105615;import com.changgou.entity.Result;
import com.changgou.entity.StatusCode;
import com.changgou.oauth.service.AuthService;
import com.changgou.oauth.util.AuthToken;
import com.changgou.oauth.util.CookieUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;import javax.servlet.http.HttpServletResponse;@Controller
@RequestMapping("/oauth")
public class AuthController {@Autowiredprivate AuthService authService;@Value("${auth.clientId}")private String clientId;@Value("${auth.clientSecret}")private String clientSecret;@Value("${auth.cookieDomain}")private String cookieDomain;@Value("${auth.cookieMaxAge}")private int cookieMaxAge;@ResponseBody@PostMapping("/login")public Result login(String username, String password){if (StringUtils.isEmpty(username)){return new Result(false, StatusCode.LOGINERROR,"用户名没有输入");}if (StringUtils.isEmpty(password)){return new Result(false, StatusCode.LOGINERROR,"密码没有输入");}AuthToken authToken =null;try {authToken = authService.login(username,password,clientId,clientSecret);this.saveJtiToCookie(authToken.getJti());} catch(Exception e) {e.printStackTrace();return new Result(false, StatusCode.LOGINERROR,"密码输入错误");}return new Result(true, StatusCode.OK,"登录成功",authToken.getJti());}private void saveJtiToCookie(String jti) {HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();CookieUtil.addCookie(response,cookieDomain,"/","uid",jti,cookieMaxAge,false);}@RequestMapping("/toLogin")public String toLogin() {return "login";}
}

Spring Securiy +aouth2.0+jwt整合,实现鉴权登录相关推荐

  1. JWT的API鉴权,基于拦截器的token与鉴权

    基于JWT的API鉴权 基于拦截器的token与鉴权 如果我们每个方法都去写一段代码,冗余度太高,不利于维护,那如何做使我们的代码看起来更清爽呢?我们可以  将这段代码放入拦截器去实现 Spring中 ...

  2. Golang jwt跨域鉴权

    Golang jwt跨域鉴权 JWT全称JSON Web Token是一种跨域认证解决方案,属于一个开放的标准,它规定了一种Token实现方式,目前多用于前后端分离项目和OAuth2.0 安装jwt ...

  3. Go语言学习笔记——jwt跨域鉴权

    文章目录 Golang jwt跨域鉴权 jwt介绍 JWT 到底是什么? JWT 和 OAuth 选择签名方法 签名方法和密钥类型 安装jwt 简单使用 生成JWT 解析jwt 测试:生成token并 ...

  4. Elasticsearch-06 Spring Boot 2.0.9整合ElasticSearch5.6.16

    文章目录 概述 官方JAVA API文档 工程 pom.xml es配置文件 Es配置类 控制层 简单查询 新增数据 删除数据 更新数据 复合查询 其他 新建索引 删除索引 判断index中某个typ ...

  5. 基于jwt的用户鉴权:拦截器概述

    基于拦截器的token与鉴权 如果我们每个方法都去写一段代码,冗余度太高,不利于维护,那如何做使我们的代码看起来更清爽呢?我们可以将这段代码放入拦截器去实现 Spring中的拦截器 Spring为我们 ...

  6. php 完全前后端分离使用jwt,larke-admin 是一套使用 Laravel 8 、JWT 和 RBAC鉴权的前后端分离的通用后台管理系统...

    StarLong (作者) 3周前 @deatil [stacktrace] #0 E:\PHPstudy\phpstudy_pro\WWW\laravel8\vendor\symfony\conso ...

  7. 【Spring Cloud Alibaba 实战 | 总结篇】Spring Cloud Gateway + Spring Security OAuth2 + JWT 实现微服务统一认证授权和鉴权

    一. 前言 hi,大家好~ 好久没更文了,期间主要致力于项目的功能升级和问题修复中,经过一年时间这里只贴出关键部分代码的打磨,[有来]终于迎来v2.0版本,相较于v1.x版本主要完善了OAuth2认证 ...

  8. 详解比springSecurity和shiro更简单优雅的轻量级Sa-Token框架,比如登录认证,权限认证,单点登录,OAuth2.0,分布式Session会话,微服务网关鉴权

    文章目录 1. 技术选型 2. Sa-Token概述 2.1 简单介绍 2.2 登录认证 2.3 权限认证 3. 功能一览 4. Sa-Token使用 4.1 引入Sa-Token依赖 4.2 Sa- ...

  9. Springboot系列之Shiro、JWT、Redis 进行认证鉴权

    Springboot系列之Shiro.JWT.Redis 进行认证鉴权 Shiro架构 Apache Shiro是一个轻量级的安全框架 Shiro可以非常容易的开发出足够好的应用,其不仅可以用在Jav ...

  10. js如何获取jwt信息_学习后端鉴权系列: 基于JWT的会话管理

    内容回顾 上一节讲了基于Cookie+Session的认证方案. Even:学习后端鉴权系列: 基于Cookie, Session认证​zhuanlan.zhihu.com 由于基于Session方案 ...

最新文章

  1. c++ 异常注意说明
  2. 使用adb命令查看Sqlite数据库
  3. 《程序员面试金典》合法括号判断
  4. 计量经济学建模_一分钟看完计量经济学
  5. matlab 水文频率曲线,【求助】如何计算水文频率,外行求教 - 地学 - 小木虫 - 学术 科研 互动社区...
  6. git报错:fatal: remote origin already exists
  7. Silverlight通过Wcf Data Service访问数据库之ADO.NET Entity Framework篇
  8. java html转图片_Python一键转Java?“Google翻译”你别闹
  9. java提示需要标识符,java错误需要标识符
  10. 编写一个简单的widget
  11. arcpy_intersectmerge
  12. linux终端文件保存,Linux 终端中命令输出保存到文件中的方法
  13. simulink仿真实例_推荐几本关于制冷仿真的书籍(制冷仿真必备)
  14. 食品的特征和鸿蒙,白粥养胃吗?知道这4种食物才是养胃高手
  15. global.php,深入理解PHP中的global
  16. ue4导入倾斜摄影_倾斜摄影如何和bim结合?倾斜摄影数据怎么导?我来告诉你!...
  17. 流媒体学习之路(WebRTC)——GCC分析(2)
  18. 定格动画android,定格动画安卓版下载-定格动画最新版下载v2.2.2-一听下载站
  19. Python pandas库|任凭弱水三千,我只取一瓢饮(5)
  20. singleSpa记录

热门文章

  1. win11 即将来临 —— 你真的会管理你的Windows 10吗?
  2. 微型计算机的硬盘电源,17款SATA硬盘盒产品横向评测
  3. !! A股历史平均市盈率走势图
  4. Excel中VBA合并工作表
  5. python绘制太阳花,Python turtle学习笔记(包含太阳花的绘制,玫瑰花的绘制)
  6. win10电脑显示未安装任何音频输出设备问题解决记录
  7. 对话乔会君丨两年服务1700家企业,洪泰智造如何锻造下一个独角兽?
  8. 时空数据生成对抗网络研究综述(下)
  9. 求解顺序统计量的7种方法
  10. PL/SQL程序设计 第八章 触发器