In Spring Cloud OAUTH2 is required to implement unified authentication and authorization for multiple microservices. By sending a certain type of grant type to OAUTH服务for central authentication and authorization, access_token is obtained. This token is trusted by other microservices. We can use access_token for subsequent access, thereby realizing unified authentication and authorization for microservices.
This example provides four major parts:
discovery-service : Basic module for service registration and discoveryauth-server :OAUTH2 certification and authorization centerorder-service : Ordinary microservice, used to verify authentication and authorizationapi-gateway : Border Gateway (all microservices are behind it)Roles in OAUTH2:
Resource Server : Resources authorized to accessAuthotization Server : OAUTH2 Certification Authorization CenterResource Owner : UserClient : Clients using APIs (such as Android, IOS, web apps)Grant Type:
Authorization Code : used between server applicationsImplicit : used in mobile apps or web apps (these apps are on the user's device, such as regulating WeChat on the mobile phone to authenticate and authorize)Resource Owner Password Credentials(password) : The application is directly trusted (all developed by a company, and this example is usedClient Credentials : Used in application API access.1. Basic environment
Use Postgres as account storage, Redis as Token storage, and start Postgres and Redis on the server using docker-compose .
Redis: image: sameersbn/redis:latest ports: - "6379:6379" volumes: - /srv/docker/redis:/var/lib/redis:Z restart: alwaysPostgreSQL: restart: always image: sameersbn/postgresql:9.6-2 ports: - "5432:5432" environment: - DEBUG=false - DB_USER=wang - DB_PASS=yunfei - DB_NAME=order volumes: - /srv/docker/postgresql:/var/lib/postgresql:Z
2.auth-server
2.1 OAuth2 service configuration
Redis is used to store token . After the service restarts, there is no need to re-get token .
@Configuration@EnableAuthorizationServerpublic class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { @Autowired private AuthenticationManager authenticationManager; @Autowired private RedisConnectionFactory connectionFactory; @Bean public RedisTokenStore tokenStore() { return new RedisTokenStore(connectionFactory); } @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints .authenticationManager(authenticationManager) .tokenStore(tokenStore()); } @Override public void configure(AuthorizationServerSecurityConfigurer security) throws Exception { security .tokenKeyAccess("permitAll()") .checkTokenAccess("isAuthenticated()"); } @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.inMemory() .withClient("android") .scopes("xx") //The scopes here are useless, you can set .secret("android") .authorizedGrantTypes("password", "authorization_code", "refresh_token") .and() .withClient("webapp") .scopes("xx") .authorizedGrantTypes("implicit"); }}2.2 Resource service configuration
auth-server provides user information, so auth-server is also a Resource Server
@Configuration@EnableResourceServerpublic class ResourceServerConfig extends ResourceServerConfigurerAdapter { @Override public void configure(HttpSecurity http) throws Exception { http .csrf().disable() .exceptionHandling() .authenticationEntryPoint((request, response, authException) -> response.sendError(HttpServletResponse.SC_UNAUTHORIZED)) .and() .authorizeRequests() .anyRequest().authenticated() .and() .httpBasic(); }} @RestControllerpublic class UserController { @GetMapping("/user") public Principal user(Principal user){ return user; }}2.3 Security Configuration
@Configurationpublic class SecurityConfig extends WebSecurityConfigurerAdapter { @Bean public UserDetailsService userDetailsService(){ return new DomainUserDetailsService(); } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth .userDetailsService(userDetailsService()) .passwordEncoder(passwordEncoder()); } @Bean public SecurityEvaluationContextExtension securityEvaluationContextExtension() { return new SecurityEvaluationContextExtension(); } //No password grant_type @Override @Bean public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); }}2.4 Permission Design
The用户(SysUser)角色(SysRole) SysRole)权限(SysAuthotity) setting is多对多. Load users and permissions through DomainUserDetailsService .
2.5 Configuration
spring: profiles: active: ${SPRING_PROFILES_ACTIVE:dev} application: name: auth-server jpa: open-in-view: true database: POSTGRESQL show-sql: true hibernate: ddl-auto: update datasource: platform: postgres url: jdbc:postgresql://192.168.1.140:5432/auth username: wang password: yunfei driver-class-name: org.postgresql.Driver redis: host: 192.168.1.140server: port: 9999eureka: client: serviceUrl: defaultZone: http://${eureka.host:localhost}:${eureka.port:8761}/eureka/logging.level.org.springframework.security: DEBUGlogging.leve.org.springframework: DEBUG## is very important security: oauth2: resource: filter-order: 32.6 Test data
Two users are initialized in data.sql admin -> ROLE_ADMIN -> query_demo , wyf -> ROLE_USER
3.order-service
3.1 Resource service configuration
@Configuration@EnableResourceServerpublic class ResourceServerConfig extends ResourceServerConfigurerAdapter{ @Override public void configure(HttpSecurity http) throws Exception { http .csrf().disable() .exceptionHandling() .authenticationEntryPoint((request, response, authException) -> response.sendError(HttpServletResponse.SC_UNAUTHORIZED)) .and() .authorizeRequests() .anyRequest().authenticated() .and() .httpBasic(); }}3.2 User information configuration
order-service is a simple microservice that uses auth-server for authentication and authorization. In its configuration file, you can specify the user information at auth-server address:
security: oauth2: resource: id: order-service user-info-uri: http://localhost:8080/uaa/user prefer-token-info: false
3.3 Permission Test Controller
Access is accessible with authority without query-demo , that is, admin user
@RestControllerpublic class DemoController { @GetMapping("/demo") @PreAuthorize("hasAuthority('query-demo')") public String getDemo(){ return "good"; }}4 api-gateway
api-gateway has 2 functions in this example:
implicit4.1 Turn off csrf and enable Oauth2 client support
@Configuration@EnableOAuth2Ssopublic class SecurityConfig extends WebSecurityConfigurerAdapter{ @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable(); }}4.2 Configuration
zuul: routes: uaa: path: /uaa/** sensitiveHeaders: serviceId: auth-server order: path: /order/** sensitiveHeaders: serviceId: order-service add-proxy-headers: truesecurity: oauth2: client: access-token-uri: http://localhost:8080/uaa/oauth/token user-authorization-uri: http://localhost:8080/uaa/oauth/authorize client-id: webapp resource: user-info-uri: http://localhost:8080/uaa/user prefer-token-info: false
5 Demo
5.1 Client calls
Use Postman to send a request to http://localhost:8080/uaa/oauth/token to get access_token (for admin users, such as 7f9b54d4-fd25-4a2c-a848-ddf8f119230b )
admin user
wyf user
5.2 Webapp call in api-gateway
No tests are done yet, and I will add them next time.
6 Source code address
https://github.com/wiselyman/uaa-zuul
The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.