前言:
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添加到请求头中即可