一、服务端
1、AuthorizationServer类,类中配置相关参数:客户端详情服务、令牌管理服务、令牌访问断电url以及令牌服务、令牌端点安全约束
package hs.lj.security.uaa.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; 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.code.AuthorizationCodeServices; import org.springframework.security.oauth2.provider.code.InMemoryAuthorizationCodeServices; import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; import org.springframework.security.oauth2.provider.token.DefaultTokenServices; import org.springframework.security.oauth2.provider.token.TokenEnhancerChain; import org.springframework.security.oauth2.provider.token.TokenStore; import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; import java.util.Arrays; @Configuration @EnableAuthorizationServer public class AuthorizationServer extends AuthorizationServerConfigurerAdapter { @Autowired private TokenStore tokenStore; @Autowired private ClientDetailsService clientDetailsService; @Autowired private AuthorizationCodeServices authorizationCodeServices;//授权码模式 @Autowired private AuthenticationManager authenticationManager;//认证管理器 @Autowired private JwtAccessTokenConverter accessTokenConverter; //令牌的管理服务 @Bean public AuthorizationServerTokenServices tokenService() { DefaultTokenServices service=new DefaultTokenServices(); service.setClientDetailsService(clientDetailsService);//客户端详情服务 service.setSupportRefreshToken(true);//支持刷新令牌 service.setTokenStore(tokenStore);//令牌存储策略 //设置令牌的增强 使用jwt令牌时使用 TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain(); tokenEnhancerChain.setTokenEnhancers(Arrays.asList(accessTokenConverter)); service.setTokenEnhancer(tokenEnhancerChain); service.setAccessTokenValiditySeconds(7200); // 令牌默认有效期2小时 service.setRefreshTokenValiditySeconds(259200); // 刷新令牌默认有效期3天 return service; } @Bean public AuthorizationCodeServices authorizationCodeServices() { //设置授权码模式的授权码如何存取,暂时采用内存方式 return new InMemoryAuthorizationCodeServices(); } //ClientDetailsServiceConfigurer:用来配置客户端详情服务(ClientDetailsService) //客户端详情信息在这里进行初始化,你能够把客户端详情信息写死在这里或者是 // 通过数据库来存储调取详情信息。 @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.inMemory()//inMemory 存储在内存中 .withClient("c1")//标识客户端id .secret(new BCryptPasswordEncoder().encode("secret"))//客户端安全码(密钥),以BC的个格式 .resourceIds("res1")//客户端可以访问的资源列表 .authorizedGrantTypes("authorization_code", "password","client_credentials","implicit","refresh_token")// 该client允许的授权类型 //authorization_code,password,refresh_token,implicit,client_credentials .scopes("all")//允许的授权范围(访问范围) all:只是一个标识 .autoApprove(false)//授权页面,false:跳转到授权页面 .redirectUris("http://www.baidu.com");//回调地址 } //AuthorizationServerEndpointsConfigurer:用来配置令牌(token) //的访问端点url和令牌服务(token services)。 @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints .authenticationManager(authenticationManager)//认证管理器 .authorizationCodeServices(authorizationCodeServices)//授权码服务 .tokenServices(tokenService())//令牌管理服务 .allowedTokenEndpointRequestMethods(HttpMethod.POST); } //AuthorizationServerSecurityConfigurer:用来配置令牌端点的安全约束. @Override public void configure(AuthorizationServerSecurityConfigurer authorizationServerSecurityConfigurer) throws Exception { authorizationServerSecurityConfigurer .tokenKeyAccess("permitAll()") //oauth/token_key是公开 .checkTokenAccess("permitAll()") //oauth/check_token公开 .allowFormAuthenticationForClients() //表单认证(申请令牌) ; } }
2、TokenConfig类
package hs.lj.security.uaa.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.oauth2.provider.token.TokenStore; import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore; import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; import org.springframework.security.oauth2.provider.token.store.JwtTokenStore; @Configuration public class TokenConfig { private String SIGNING_KEY="uaa123"; //使用内存存储令牌(普通令牌) /* @Bean public TokenStore tokenStore() { return new InMemoryTokenStore(); }*/ @Bean public TokenStore tokenStore() { return new JwtTokenStore(accessTokenConverter()); } @Bean public JwtAccessTokenConverter accessTokenConverter() { JwtAccessTokenConverter converter = new JwtAccessTokenConverter(); converter.setSigningKey(SIGNING_KEY); //对称秘钥,资源服务器使用该秘钥来验证 return converter; } }
3、WebSecurityConfig配置,类中配置认证管理器、密码编辑器、安全拦截机制(较为重要)
package hs.lj.security.uaa.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.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.provisioning.InMemoryUserDetailsManager; @Configuration @EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true) public class WebSecurityConfig extends WebSecurityConfigurerAdapter { //认证管理器 @Bean public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } //密码编码器 @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } //安全拦截机制(最重要) @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .authorizeRequests() .antMatchers("/r/r1").hasAnyAuthority("p1") .antMatchers("/login*").permitAll() .anyRequest().authenticated() .and() .formLogin(); } }
4、UserDetailsService配置 配置用户认证
package hs.lj.security.uaa.service;
import com.alibaba.fastjson.JSON;
import hs.lj.security.uaa.dao.UserDao;
import hs.lj.security.uaa.model.UserDto;
import org.springframework.beans.factory.annotation.Autowired;
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;
import java.util.ArrayList;
import java.util.List;
@Service
public class SpringDataUserDetailsService implements UserDetailsService {
@Autowired
UserDao userDao;//自己配置的mapper映射,从数据库中查询数据用
//根据 账号查询用户信息
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//将来连接数据库根据账号查询用户信息
UserDto userDto = userDao.getUserByUsername(username);
if(userDto == null){
//如果用户查不到,返回null,由provider来抛出异常
return null;
}
System.out.println("用户名:"+username+"*****密码:"+userDto.getPassword());
List<String> permissions=new ArrayList<>();
permissions.add("p1");
String[] permissionArray = new String[permissions.size()];
permissions.toArray(permissionArray);
//将userDto转成json
String principal = JSON.toJSONString(userDto);
System.out.println("/****//////////****////"+principal);
UserDetails userDetails = User.withUsername(principal).password(userDto.getPassword()).authorities(permissionArray).build();
return userDetails;
}
}
5、启动类
package hs.lj.security.uaa; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.netflix.hystrix.EnableHystrix; import org.springframework.cloud.openfeign.EnableFeignClients; @SpringBootApplication @EnableDiscoveryClient @EnableHystrix @EnableFeignClients(basePackages = {"hs.lj.security.uaa"}) public class UaaApplication { public static void main(String[] args) { SpringApplication.run(UaaApplication.class,args); } }
6、相关依赖
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>Security1</artifactId> <groupId>hs.lj</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>Security1-uaa</artifactId> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <dependency> <groupId>com.netflix.hystrix</groupId> <artifactId>hystrix-javanica</artifactId> </dependency> <dependency> <groupId>org.springframework.retry</groupId> <artifactId>spring-retry</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</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>org.springframework.data</groupId> <artifactId>spring-data-commons</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-oauth2</artifactId> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-jwt</artifactId> </dependency> <dependency> <groupId>javax.interceptor</groupId> <artifactId>javax.interceptor-api</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.18</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> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> </dependencies> </project>
二、用户端
1、ResourceServerConfig类
package hs.lj.security.author.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.http.SessionCreationPolicy; 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.config.annotation.web.configurers.ResourceServerSecurityConfigurer; import org.springframework.security.oauth2.provider.token.RemoteTokenServices; import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices; import org.springframework.security.oauth2.provider.token.TokenStore; @Configuration @EnableResourceServer public class ResourceServerConfig extends ResourceServerConfigurerAdapter { public static final String RESOURCE_ID="res1"; @Autowired TokenStore tokenStore; @Override public void configure(ResourceServerSecurityConfigurer resources) { resources.resourceId(RESOURCE_ID)//资源ID .tokenStore(tokenStore) //.tokenServices(tokenService())//验证令牌的服务 .stateless(true); } @Override public void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/**").access("#oauth2.hasScope('all')") .and().csrf().disable() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); } /* //令牌验证的服务。。。。该种类型的服务应用于非jwt令牌 //资源服务令牌解析服务 @Bean public ResourceServerTokenServices tokenService() { //使用远程服务请求授权服务器校验token,必须指定校验token 的url、client_id,client_secret RemoteTokenServices service=new RemoteTokenServices(); service.setCheckTokenEndpointUrl("http://localhost:53020/uaa/oauth/check_token"); service.setClientId("c1"); service.setClientSecret("secret"); return service; }*/ }
2、TokenConfig
package hs.lj.security.author.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; 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; @Configuration public class TokenConfig { private String SIGNING_KEY="uaa123"; //使用内存存储令牌(普通令牌) /* @Bean public TokenStore tokenStore() { return new InMemoryTokenStore(); }*/ @Bean public TokenStore tokenStore() { return new JwtTokenStore(accessTokenConverter()); } @Bean public JwtAccessTokenConverter accessTokenConverter() { JwtAccessTokenConverter converter = new JwtAccessTokenConverter(); converter.setSigningKey(SIGNING_KEY); //对称秘钥,资源服务器使用该秘钥来验证 return converter; } }
3、WebSecurityConfig
package hs.lj.security.author.config; import org.springframework.context.annotation.Configuration; 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.WebSecurityConfigurerAdapter; @Configuration @EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true) public class WebSecurityConfig extends WebSecurityConfigurerAdapter { //安全拦截机制(最重要) @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .authorizeRequests() // .antMatchers("/r/r1").hasAuthority("p2") // .antMatchers("/r/r2").hasAuthority("p2") .antMatchers("/r/**").authenticated()//所有/r/**的请求必须认证通过 .anyRequest().permitAll()//除了/r/**,其它的请求可以访问 ; } }
4、启动类
package hs.lj.security.author; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @SpringBootApplication @EnableDiscoveryClient public class AuthorApplication { public static void main(String[] args) { SpringApplication.run(AuthorApplication.class,args); } }
5、相关依赖
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>Security1</artifactId> <groupId>hs.lj</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>Security1_Author</artifactId> <dependencies> <!--<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring‐cloud‐starter‐netflix‐eureka‐client</artifactId> </dependency>--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-oauth2</artifactId> </dependency> <dependency> <groupId>javax.interceptor</groupId> <artifactId>javax.interceptor-api</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> </dependencies> </project>