preparation
Firstly, the UserDetailsService interface needs to be implemented to complete the loading of users; Note that the password here needs to be encrypted. If the database is plaintext, it needs to be encrypted and set later
Furthermore, a UserDetails interface needs to be implemented to complete the external output of user information;
In addition, it is necessary to implement a GrantedAuthority interface to complete the external output of user permissions;
Create an add / remove class for @ bean to return PasswordEncode. It is recommended to use the ready-made BCryptPasswordEncoder, or you can implement the PasswordEncoder interface and customize the encryption algorithm yourself
Create a class that inherits WebSecurityConfigurerAdapter
Override his configure (HttpSecurity http) method for Security related configuration
@Configuration @EnableWebSecurity // Start WebSecurity [can be written in the configuration class] public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() // Temporarily closed for testing .authorizeRequests() .antMatchers("/oauth/**","/login/**","/logout/**") // Create matching rule .permitAll() // Release the matching rules described above .anyRequest().authenticated() // To switch to any request, the settings must be authenticated before they can be accessed .and().formLogin().permitAll(); // And release the form certification } }
Different configurations are made for resources and authentication servers
Authorization server configuration
Create a class to inherit the AuthorizationServerConfigurerAdapter and override the configure(ClientDetailsServiceConfigurer clients) method
Configure the authorization server to load the authorization information of cooperative merchants, resource permission, authorization method and callback address
/** * Authorization server configuration * @author Guochao */ @Configuration @EnableAuthorizationServer // Enable authorization server public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { @Autowired private PasswordEncoder passwordEncoder; // Configure client @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { // Load partner app information // TODO formal environment uses this. Now it is convenient to test and use memory based configuration clients JDBC (), account and password data can also be checked in the database clients.inMemory() .withClient("pzh") // clientId, client id .secret(passwordEncoder.encode("123456")) // The client password can be encrypted // The redirected address. After the user agrees to authorize, he will carry the authorization code and request the callback address to obtain the authorization code .redirectUris("https://www.baodu.com") .scopes("all","userinfo","resource") // Allowable scope of authorization .authorizedGrantTypes("authorization_code") // Authorization type. Select the authorization code mode here .autoApprove("all","userinfo") // Automatic authorization // After automatic authorization is set, you can request permissions within the authorization and directly complete the authorization. Those outside the authorization will still jump to the user consent interface, // If you do not set the scope, or if you enter multiple scopes, one of them does not contain automatic authorization, all optional scopes will appear // . autoApprove(true) / / absolute automatic authorization. There is no need to write specific scopes that allow automatic authorization. All scopes allow automatic authorization } }
Resource server configuration
@Configuration @EnableResourceServer // Enable resource services public class ResourceServerConfig extends ResourceServerConfigurerAdapter { @Override public void configure(HttpSecurity http) throws Exception { http.authorizeRequests() // Configure resource information with resource domain restrictions .antMatchers("/userinfo/**").access("#oauth2.hasAnyScope('userinfo','all')") .and() // Matching resources: match the addresses of the above resources. The resources configured in them will be protected and can only be accessed after all authentication .requestMatchers().antMatchers("/resource/**") // The access rights of this resource are configured above. Protection still needs to be configured here .antMatchers("/userinfo/**") .and() // Specify any request, and set r any request to be accessed after authorization .authorizeRequests().anyRequest().authenticated() .and().csrf(); } }
Next, we will test the authorization code mode:
The first is to obtain the authorization code
Partner client id=pzh,
Callback address = www.baidu.com com
Response mode = code
Resource field = all
Obtain authorization code
http://localhost:9999/oauth/authorize?response_type=code&client_id=pzh&redirect_uri=https://www.baidu.com&scope=all
Space each scope authorization when requesting multiple authorizations
http://localhost:9999/oauth/authorize?response_type=code&client_id=pzh&redirect_uri=https://www.baidu.com&scope=all userinfo&state=iuza79Mlap
After testing, it is found that it can simplify:
http://localhost:12301/oauth/authorize?response_type=code&client_id=pzh In this way, if scpe is not specified, all allowed scop es will be listed for users to choose, and the options depend on the merchant's registration information
After the user agrees, it will be redirected to the callback address set by the merchant, and the code authorization code will be attached. If we add the state parameter at the same time, the authorization code will also be returned when we return it. You can use state as consistency verification to prevent scrf attacks
Exchange authorization code for access_token
All information must be consistent with that filled in by the registered merchant
Code = authorization code
grant_type = authentication mode
redirect_uri = callback address
client_id = client id,
At the same time, you need to use the client id and password, and use the basic auth mode to log in
After logging in, you can get the access token
{ "access_token": "8d1a8b93-f963-4f5c-8cc1-267f099cbbd1", "token_type": "bearer", "expires_in": 42645, "scope": "all" }
Using access_token reads user resources
http://localhost:9999/oauth/token?code=7BxIn2&grant_type=authorization_code&redirect_uri=https://www.baidu.com&scope=all&client_id=pzh
Sample
Basic dependence
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.5.RELEASE</version> </parent> <properties> <spring.cloud-version>Hoxton.SR8</spring.cloud-version> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring.cloud-version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <!--System--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <version>2.3.3.RELEASE</version> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </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> <!--Tool--> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.8.1</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.22</version> <scope>provided</scope> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.75</version> </dependency> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-core</artifactId> <version>5.7.9</version> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.0</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>2.3.3.RELEASE</version> </plugin> </plugins> </build>
UserDetails example
// The class used to extract user information from the framework is responsible for providing the framework with basic attribute acquisition methods; @Data public class UserDetail implements UserDetails { private String password; private String username; private List<GrantedAuthority> auth; @Override public Collection<? extends GrantedAuthority> getAuthorities() { return this.auth; } @Override public String getPassword() { return this.password; } @Override public String getUsername() { return this.username; } @Override public boolean isAccountNonExpired() { return true; } @Override public boolean isAccountNonLocked() { return true; } @Override public boolean isCredentialsNonExpired() { return true; } @Override public boolean isEnabled() { return true; } public UserDetail() { } public UserDetail(String password, String username, List<GrantedAuthority> auth) { this.password = password; this.username = username; this.auth = auth; } // Provides a string conversion array method for easy calling public UserDetail(String password, String username, String auth) { this.password = password; this.username = username; List<String> strAuths = Arrays.asList(auth.split(",")); this.auth=strAuths.size()==0?new ArrayList<>():strAuths.stream().map(MyGrantedAuthority::new).collect(Collectors.toList()); } }
loadUsername sample
/** * User loading */ @Service public class UserLoad implements UserDetailsService { @Autowired private UserService userService; @Autowired private PasswordEncoder passwordEncoder; // Load user, password encryption @Override public UserDetails loadUserByUsername(String name) throws UsernameNotFoundException { User user = userService.getUser(name); return new UserDetail(passwordEncoder.encode(user.getPwd()), user.getName(), user.getAuth()); } }
security configuration example of others
@Configuration @EnableWebSecurity public class SpringSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { //authorizeRequests indicates the permission required to start the description http.httpBasic() .and() .formLogin().loginPage("/login.html") .defaultSuccessUrl("/admin/index.html") .loginProcessingUrl("/login").failureUrl("/error.html") .and() .logout().logoutSuccessUrl("/login.html") .and() .authorizeRequests() .antMatchers("/login.html").permitAll() .antMatchers("/error.html").permitAll() .antMatchers("/css/**").permitAll() .antMatchers("/js/**").permitAll() .antMatchers("/img/**").permitAll() .antMatchers("/plugins/**").permitAll() .and() .authorizeRequests() .antMatchers("/**").hasRole("USER") .anyRequest().authenticated() .and().csrf().disable(); http.headers().frameOptions().sameOrigin(); } }
Other people's authentication server configuration
@Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { // Configure client clients // Use memory settings .inMemory() // client_id .withClient("client") // client_secret .secret(passwordEncoder.encode("secret")) // Authorization type: authorization code, refresh token, password, client, simplified mode, SMS verification code "refresh_token" .authorizedGrantTypes("authorization_code", "password", "client_credentials", "implicit", "sms_code") // The authorization scope can also be used for authentication according to the scope ID .scopes("admin:org","write:org","read:org") .accessTokenValiditySeconds(300) .refreshTokenValiditySeconds(3000) // Whether the authorization page of authorization code mode is authorized automatically //.autoApprove(false) // Permissions owned .authorities("add:user") // Resource service ID allowed to access //.resourceIds("oauth2-resource-server001-demo") // Register callback address .redirectUris("http://localhost:20000/code"); } https://blog.csdn.net/qq_43437874/article/details/121552989