SSO是为了解决一个用户在鉴权服务器登陆过一次以后,可以在任何应用中畅通无阻,一次登陆,多系统访问
Session共享 SpringSession + Redis 配置文件spring.redis.host=localhost #spring.redis.password= spring.redis.port=6379 spring.security.user.name=123 spring.security.user.password=123 server.port=81依赖
OAuth2.0org.springframework.boot spring-boot-starter-securityorg.springframework.boot spring-boot-starter-testtest org.junit.vintage junit-vintage-engineorg.springframework.security spring-security-testtest org.springframework.boot spring-boot-starter-data-redisorg.springframework.session spring-session-data-redisorg.springframework.boot spring-boot-starter-web
OAuth 的核心就是向第三方应用颁发令牌
能够做到一个应用向用户征求授权,来向资源服务器获取资源
应用场景- 单点登录
- 第三方登录
Resource Owner
资源拥有者,对应微信的每个用户微信上设置的个人信息是属于每个用户的,不属于腾讯。
Resource Server
资源服务器,一般就是用户数据的一些操作(增删改查)的REST API,比如微信的获取用户基本信息的接口。
Client Application
第三方客户端,对比微信中就是各种微信公众号开发的应用,第三方应用经过认证服务器授权后即可访问资源服务器的REST API来获取用户的头像、性别、地区等基本信息。
Authorization Server
认证服务器,验证第三方客户端是否合法。如果合法就给客户端颁布token,第三方通过token来调用资源服务器的API。
授权认证流程 授权类型anthorization_code
授权码类型,适用于Web Server Application。模式为:客户端先调用/oauth/authorize/进到用户授权界面,用户授权后返回code,客户端然后根据code和appSecret获取access token。
implicit 简化类型,相对于授权码类型少了授权码获取的步骤。客户端应用授权后认证服务器会直接将access token放在客户端的url。客户端解析url获取token。这种方式其实是不太安全的,可以通过https安全通道和缩短access token的有效时间来较少风险。
password
密码类型,客户端应用通过用户的username和password获access token。适用于资源服务器、认证服务器与客户端具有完全的信任关系,因为要将用户要将用户的用户名密码直接发送给客户端应用,客户端应用通过用户发送过来的用户名密码获取token,然后访问资源服务器资源。比如支付宝就可以直接用淘宝用户名和密码登录,因为它们属于同一家公司,彼此充分信任。
client_credentials
客户端类型,是不需要用户参与的一种方式,用于不同服务之间的对接。比如自己开发的应用程序要调用短信验证码服务商的服务,调用地图服务商的服务、调用手机消息推送服务商的服务。当需要调用服务是可以直接使用服务商给的appID和appSecret来获取token,得到token之后就可以直接调用服务。
其他- scope:访问资源服务器的哪些作用域。一组权限,Role
- refresh token:当access token 过期后,可以通过refresh token重新获取access token。
https://developers.weixin.qq.com/doc/oplatform/Mobile_App/WeChat_Login/Development_Guide.html
实现 依赖认证服务器4.0.0 org.springframework.boot spring-boot-starter-parent2.2.7.RELEASE com.mashibing.admin o10.0.1-SNAPSHOT o1 Demo project for Spring Boot 1.8 Hoxton.SR4 org.springframework.boot spring-boot-starter-securityorg.springframework.boot spring-boot-starter-weborg.springframework.boot spring-boot-starter-testtest org.junit.vintage junit-vintage-engineorg.springframework.security spring-security-testtest org.springframework.cloud spring-cloud-starter-oauth2org.springframework.boot spring-boot-starter-data-redisorg.springframework.cloud spring-cloud-dependencies${spring-cloud.version} pom import org.springframework.boot spring-boot-maven-plugin
@EnableAuthorizationServer
@Configuration
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory().withClient("client")
.redirectUris("http://localhost:81/order")
.scopes("read","write")
.secret("secret")
.authorizedGrantTypes("authorization_code","password","implicit","client_credentials");}
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
super.configure(security);
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager);
}
@Autowired
@Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
}
security配置
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin()
.and().csrf().disable()
.authorizeRequests().anyRequest().authenticated();
}
@Override
public void configure(WebSecurity web) throws Exception {
super.configure(web);
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("111").password("222").authorities("user")
.and().withUser("admin").password("admin").authorities("admin");
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
资源服务器
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableResourceServer
@Configuration
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.antMatcher("/oauth2/api
public class JwtUtil {
private static String secret = "ko346134h_we]rg3in_yip1!";
public static String createToken(String subject, Date issueDate) {
Calendar c = Calendar.getInstance();
c.setTime(issueDate);
c.add(Calendar.DAY_OF_MONTH, 20);
String compactJws = Jwts.builder()
.setSubject(subject)
.setIssuedAt(issueDate)
.setExpiration(c.getTime())
.signWith(io.jsonwebtoken.SignatureAlgorithm.HS512, secret)
.compact();
return compactJws;
}
public static String parseToken(String token) {
try {
Claims claims = Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
if (claims != null){
return claims.getSubject();
}
}catch (ExpiredJwtException e){
e.printStackTrace();
System.out.println("jwt过期了");
}
return "";
}
}
pom依赖
Filter校验io.jsonwebtoken jjwt0.7.0
@WebFilter(filterName = "authFilter", urlPatterns = "/**")
@Component
public class MyFi implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
String token = req.getHeader("token");
if (token != null) {
// 判断解析token是否成功
String parseToken = JwtUtil.parseToken(token);
if (!StringUtils.isEmpty(parseToken)) {
System.out.println("auth success");
chain.doFilter(request, response);
}
} else {
System.out.println("auth failed");
}
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// TODO Auto-generated method stub
System.out.println("来了老弟");
Filter.super.init(filterConfig);
}
暑期编程PK赛
得CSDN机械键盘等精美礼品!


