前言:

    根据oauth2协议,采用code授权模式,通过调用/oauth/authorize获取授权码,在通过授权码获取token,这样就可以通过token访问资源服务器接口了。

一. 编写认证服务器项目

    springboot版本2.x,spring oauth2采用2.0,引入依赖

<!-- 由于一些注解和API从spring security5.0中移除,所以需要导入下面的依赖包  -->
<dependency>
    <groupId>org.springframework.security.oauth.boot</groupId>
    <artifactId>spring-security-oauth2-autoconfigure</artifactId>
    <version>2.0.0.RELEASE</version>
</dependency>

 <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</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-test</artifactId>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-test</artifactId>
    <scope>test</scope>
</dependency>

配置授权服务器: OAuth2AuthorizationServer

//授权服务器配置
@Configuration
@EnableAuthorizationServer
public class OAuth2AuthorizationServer extends
        AuthorizationServerConfigurerAdapter {

    @Override
    public void configure(ClientDetailsServiceConfigurer clients)
            throws Exception {
        clients.inMemory()
            .withClient("clientapp")
            .secret("112233")
            .redirectUris("http://localhost:9001/callbackCode")
            // 授权码模式
            .authorizedGrantTypes("authorization_code")
            .scopes("read_userinfo", "read_contacts");
    }

}

配置资源服务器:OAuth2ResourceServer

/**
 * 权限拦截在资源拦截前面
 */

@Configuration
@EnableResourceServer
public class OAuth2ResourceServer extends ResourceServerConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .anyRequest()
            .authenticated()
        .and()
            .requestMatchers()
            .antMatchers("/api/**");
    }

}

配置登陆认证:SecurityConfig

/**
 * @author LLJia
 * @version 1.0
 * @date 2019/9/11 10:12
 */

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .passwordEncoder(new Md5PasswordEncoder())
                .withUser("admin")
                .password(new Md5PasswordEncoder().encode("123456"))
                .roles("USER");
    }

    @Bean
    public Md5PasswordEncoder passwordEncoder() {
        return new Md5PasswordEncoder();
    }

}

配置資源api

@Controller
public class UserController {

   // 资源API
    @RequestMapping("/api/userinfo")
    public ResponseEntity<UserInfo> getUserInfo() {
        User user = (User) SecurityContextHolder.getContext()
                .getAuthentication().getPrincipal();
        String email = user.getUsername() + "@spring2go.com";

        UserInfo userInfo = new UserInfo();
        userInfo.setName(user.getUsername());
        userInfo.setEmail(email);

        return ResponseEntity.ok(userInfo);
    }

}

二. 配置客戶端

2.1 code模式

简单的spring web服务器,配置获取授权码和token链接

oauth.authorize=http://localhost:8080/oauth/authorizeclient_id=clientapp&redirect_uri=http://localhost:9001/callbackCode&response_type=code&scope=read_userinfo
oauth.token=http://localhost:8080/oauth/token?grant_type=authorization_code&redirect_uri=http://localhost:9001/callbackCode&scope=read_userinfo

配置访问用户信息接口

@RequestMapping("/userInfo")
public String useInfo(HttpServletRequest request, Model model) {
    HttpSession session = request.getSession();
    Object token = session.getAttribute("access_token");
    //token空跳转到认证服务器认证
    if (token == null) {
        return "redirect:" + oauthAuthorizeUrl;
    }

    //通过token获取用户信息
    String userUrl = "http://localhost:8080/api/userinfo?access_token=" + token;

    String result3 = HttpRequest.post(userUrl)
            .timeout(20000)//超时,毫秒
            .execute().body();
    model.addAttribute("userInfo", result3);

    return "userInfo";
}

配置获取code回调接口

@RequestMapping("/callbackCode")
public String callbackCode(HttpServletRequest request) {
    //获取授权码
    String code = request.getParameter("code");
    // 通过授权码调用token接口获取token
    String url = oauthTokenUrl + "&code=" + code;
    if (code != null && !code.equals("")) {
        String result2 = HttpRequest.post(url)
                .basicAuth("clientapp", "112233")
                .timeout(20000)//超时,毫秒
                .execute().body();

        JSONObject jsonObject = JSONUtil.parseObj(result2);
        String access_token = jsonObject.getStr("access_token");

        HttpSession session = request.getSession();
        //存储session里
        session.setAttribute("access_token", access_token);

        return "redirect:userInfo";
    } else {
        return "CodeError";
    }

}

三. 测试

访问客户端用户接口 http://localhost:9001/userInfo,判断token不在跳转到认证服务器认证

spring oauth2 chapter1 - 配置简单的认证服务器(本人)-LMLPHP

登陆成功调用客户端回调接口处理:

spring oauth2 chapter1 - 配置简单的认证服务器(本人)-LMLPHP

通过认证服务器返回的code调用认证服务器/oauth/token获取token,token存储到session跳转到用户action,用户action通过token访问资源服务器用户信息

spring oauth2 chapter1 - 配置简单的认证服务器(本人)-LMLPHP

2.2 password模式

09-24 18:01