前言:
1.本博文需要一定的spring-security和oauth2协议基础
2.spring-cloud版本:Dalston.SR2
1.添加pom依赖
<properties>
<learn.spring.security>0.0.1-SNAPSHOT</learn.spring.security>
</properties>
<!-- 添加spring版本依赖管理器 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.spring.platform</groupId>
<artifactId>platform-bom</artifactId>
<version>Brussels-SR4</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.SR2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.social</groupId>
<artifactId>spring-social-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.social</groupId>
<artifactId>spring-social-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.social</groupId>
<artifactId>spring-social-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.social</groupId>
<artifactId>spring-social-web</artifactId>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
</dependencies>
3.要实现oauth2认证非常简单,只需要一个@EnableAuthorizationServer标注的bean就行:
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.stereotype.Component;
@Component
@EnableAuthorizationServer
public class MyAuthenticationServerConfig{
}
4.这时候,就能启动服务了
如果发现clientId和secret打印,则代表服务已经启动成功
5.测试服务:
5.1 输入地址:http://127.0.0.1:8080/oauth/authorize?response_type=code&client_id=dj&redirect_uri=http://www.baidu.com&scope=all,回车,系统会显示需要用户名和密码,使用spring-security默认的用户名和密码即可,
默认用户名为user,默认密码为服务启动时控制台上打印出的密码。
获取授权时系统会显示403异常,这是因为spring-security-oauth2默认登陆的用户必须得有ROLE_USER角色才能获得授权授权
6.自定义用户认证逻辑
spring-security处理用户信息获取逻辑封装在UserDetailsService接口中,我们只需实现这个接口即可
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.social.security.SocialUser; import org.springframework.social.security.SocialUserDetails; import org.springframework.social.security.SocialUserDetailsService; import org.springframework.stereotype.Component; /** * UserDetailsService负责控制用户发送的登陆信息, * 如果发送的登录信息与返回的userDetails相同,才会允许登陆 * @author Administrator * */ @Component public class MyUserDetailService implements UserDetailsService, SocialUserDetailsService{ Logger logger = LoggerFactory.getLogger(getClass()); @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { logger.debug("表单登录用户名:" + username); return buildUser(username); } @Override public SocialUserDetails loadUserByUserId(String userId) throws UsernameNotFoundException { logger.info("设计登录用户id:" + userId); return buildUser(userId); } private SocialUserDetails buildUser(String userId) { String password = "123456"; String userName = "user"; return new SocialUser(userName, password, true, true, true, true, AuthorityUtils.createAuthorityList("admin"/*, "ROLE_USER"*/)); } }
重启服务,再次获取授权,这次会弹出是否授权认证页面
选择Approve,点击Authorize,系统会重定向到我们指定的URL,并将授权码添加到URL参数中
7.使用授权码获取access_token
使用postman携带认证信息和参数发送请求信息:
access_token获取成功
8.使用用户名密码获取access_token
用认证码和用户名密码获取到的access_token相同,因为spring-security-oauth2无论使用认证码或用户名密码方式,都会去保存access_token的地方先找到当前用户是否已存在access_token,若已存在,则直接返回,不存在则先生成一个保存之后再返回。
9.携带access_token获取资源
9.1 使用access_token获取资源首先要启动资源服务器,只需在一个配置类上加上@EnableResourceServer即可
import org.springframework.context.annotation.Configuration; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; @Configuration @EnableResourceServer public class MyResourcesServerConfig { }
9.2 添加一个Controller
import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class DemoController { @GetMapping("/demo") public UserDetails demo(@AuthenticationPrincipal UserDetails user) { return user; } }
9.3 使用postman,将access_token添加到请求头中即可