Build your own management system step by step ① Spring Security OAuth + jwt

Now Spring boot greatly simplifies the configuration of Spring Framework applications, and the basic security of the program can be achieved through simple dependency configuration.

First let's take a look at oauth 2.0

The specification of OAuth 2.0 can refer to:  RFC 6749

OAuth is an open standard that allows a user to allow third-party applications to access private resources (such as photos, videos, contact lists) stored by the user on a website without providing the user name and password to the third-party application. Currently, the latest version of OAuth is 2.0

OAuth allows users to provide a token instead of a username and password to access their data stored with a specific service provider. Each token authorizes a specific website (eg, a video editing website) to access a specific resource (eg, just a video in a certain album) for a specified period of time (eg, within the next 2 hours). In this way, OAuth allows users to authorize third-party websites to access information they store on another service provider without sharing their access permissions or the entirety of their data.

 

  • resource owner: resource owner, referring to the "user" of the terminal
  • resource server: A resource server, that is, a service provider that stores protected resources. To access these resources, you need to obtain an access token (access token). It and the authentication server can be the same server or a different server. If we visit the Sina Blog website, then if we use the Sina Blog account to log in to the Sina Blog website, then the resources of Sina Blog and the authentication of Sina Blog are the same, which can be considered to be the same server. If we log in to Zhihu with a Sina blog account, then obviously Zhihu's resources and Sina's authentication are not the same server.
  • client: A client that represents a third-party application that makes resource requests to protected resources.
  • authorization server: The authorization server will issue an access token to the client after verifying the resource owner and obtaining authorization. 
          

In our system we need to add dependency library.

· spring-boot-starter-web

· spring-boot-starter-security

· spring-boot-starter-web

· spring-security-jwt 

· spring-security-oauth2

see here

The main directory structure of the configuration is like this

First configure Spring boot's configuration file application.properties

security.oauth2.resource.filter-order=3

security.signing-key=MaYzkSjmkzPC57L
security.security-name=fmanager

security.jwt.client-id=testjwtclientid
security.jwt.client-secret=XY7kmzoNzl100
security.jwt.client-role=ADMIN_USER
security.jwt.grant-type=password
security.jwt.scope-read=read
security.jwt.scope-write=write
security.jwt.resource-ids=testjwtresourceid

#需要的是上面部分

# LOGGING
logging.level.org.springframework.web=DEBUG
logging.level.main.java.com.fmanager = DEBUG


spring.datasource.url=jdbc:postgresql://localhost:5432/fmanager
spring.datasource.username=xxxxx
spring.datasource.password=xxxx

mybatis.config-locations=classpath:mybatis/mybatis-config.xml
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml

security configuration,

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Value("${security.signing-key}")
    private String signingKey;
    
    @Value("${security.security-name}")
    private String securityRealm;
    
    
    @Resource
    private UserDetailsService userDetailsService; 
    
    
    @Bean
    @Override
    protected AuthenticationManager authenticationManager() throws Exception {
       return super.authenticationManager();
    }
    
    
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
       auth.userDetailsService(userDetailsService)
               .passwordEncoder(new BCryptPasswordEncoder());
    }
    
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
       http
               .sessionManagement()
               .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
               .and()
               .httpBasic()
               .realmName(securityRealm)
               .and()
               .csrf()
               .disable().authorizeRequests().antMatchers("/oauth/token").permitAll(); //$NON-NLS-1$

    }
    
    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setSigningKey(signingKey);
        return converter;
    }
    
    @Bean
    public TokenStore tokenStore() {
        return new JwtTokenStore(accessTokenConverter());
    }
    
    @Bean
    @Primary //Making this primary to avoid any accidental duplication with another token service instance of the same name
    public DefaultTokenServices tokenServices() {
        DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
        defaultTokenServices.setTokenStore(tokenStore());
        defaultTokenServices.setSupportRefreshToken(true);
        return defaultTokenServices;
    }  
}
  • Note to add
  • JwtTokenStore and JwtAccessTokenConverter beans: JwtAccessTokenConverter is to be used in authorization server and resource server, JwtTokenStore is used to decode token in resource server.
  • UserDetailsService: We inject our own UserDetailsServiceImpl (click to view) service, so that we can achieve authentication through username and password
  • Password encryption uses BCryptPasswordEncoder provided by spring

Authorization server configuration

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

	@Value("${security.jwt.client-id}")
	private String clientId;

	@Value("${security.jwt.client-secret}")
	private String clientSecret;

	@Value("${security.jwt.grant-type}")
	private String grantType;

	@Value("${security.jwt.scope-read}")
	private String scopeRead;

	@Value("${security.jwt.scope-write}")
	private String scopeWrite = "write"; //$NON-NLS-1$

	@Value("${security.jwt.resource-ids}")
	private String resourceIds;

	@Autowired
	private TokenStore tokenStore;

	@Autowired
	private JwtAccessTokenConverter accessTokenConverter;

	@Autowired
	private AuthenticationManager authenticationManager;

	@Autowired
	private PasswordEncoder passwordEncoder;

	@Override
	public void configure(ClientDetailsServiceConfigurer configurer) throws Exception {

		configurer.inMemory().withClient(clientId).secret(passwordEncoder.encode(clientSecret))
				.authorizedGrantTypes(grantType).scopes(scopeRead, scopeWrite).resourceIds(resourceIds);
	}

	@Override
	public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
		TokenEnhancerChain enhancerChain = new TokenEnhancerChain();
		enhancerChain.setTokenEnhancers(Arrays.asList(accessTokenConverter));
		endpoints.tokenStore(tokenStore).accessTokenConverter(accessTokenConverter).tokenEnhancer(enhancerChain)
				.authenticationManager(authenticationManager);
	}

	@Bean
	private static DelegatingPasswordEncoder passwordEncoder() {
		String idForEncode = "bcrypt"; //$NON-NLS-1$
		Map<String, PasswordEncoder> encoderMap = new HashMap<>();
		encoderMap.put(idForEncode, new BCryptPasswordEncoder());
		return new DelegatingPasswordEncoder(idForEncode, encoderMap);
	}

}
  • Inherit AuthorizationServerConfigurerAdapter and implement the configuration inside
  • Client id, Client secret, provide authentication client id and password
  • scope : defines the access resource level
  • AuthenticationManager : Spring's authentication manager

Resource server configuration

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
    
    @Autowired
    private ResourceServerTokenServices tokenServices;
    
    
    @Value("${security.jwt.resource-ids}")
    private String resourceIds;
    
    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        resources.resourceId(resourceIds).tokenServices(tokenServices);
    }
    
    
    @Override
    public void configure(HttpSecurity http) throws Exception {
                http
                .requestMatchers()
                .and()
                .authorizeRequests()
                .antMatchers("/**").authenticated(); //$NON-NLS-1$
    }

}
  • Configure resource access in the configure method, here I configured all urls to require authentication

The configuration is basically completed, and the configuration of connecting to the database is also very simple. Add mybastis configuration and spring connection configuration in application.properties

spring.datasource.url=jdbc:postgresql://localhost:5432/fmanager
spring.datasource.username=xxxxx
spring.datasource.password=xxxx

mybatis.config-locations=classpath:mybatis/mybatis-config.xml
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml

Just write the corresponding mapper

for example:

@Mapper
public interface UserDAO {
	public User findById(long id);
	
	public User findByUserName(String name);
}
  • Note that the annotation (Mapper) should be added, so that the system will not be automatically loaded

Well, first write a test Controller

@RestController
@RequestMapping("/test")
public class TestController {
	
    @Autowired
    private UserServcie userService;
    
	@RequestMapping(value="/greeting",method = RequestMethod.GET)
    public String greeting() {
	    System.out.println(userService.findById(1));
        return "Hello";
    }
	
	
}

Access with rest client will see

permission denied.

Here we use the username and password to get the token

To get this token, remember to add

Content-Type:application/x-www-form-urlencoded
authorization: Basic dGVzdGp3dGNsaWVudGlkOlhZN2ttem9OemwxMDA=   

This authorization is obtained through the previous client_id and client_secret base64.

get this token, 

Then we can access the test controller with this token when we visit the test controller again.

 

 

 

 

 

 

 

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324465116&siteId=291194637