1、使用springsecurity普通登录 https://mrbird.cc/Spring-Security-Authentication.html
1-1、Spring Security的核心思想是用户授权和资源认证。
- 资源认证:认证访问系统的用户,是调用authenticationManager.authenticate()方法来获得证书authentication,一般我们采用用户名、密码方式认证,那么authentication的实现类就是UsernamePasswordAuthentication。
- 用户授权:是让用户可以访问哪些资源,一般在WebSecurityConfigurerApdater的继承类中编写。
1-2、userService:用户和密码是否准确可以写到里边去。
package cc.mrbird.security.browser;
import cc.mrbird.domain.MyUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
public class UserDetailService implements UserDetailsService {
@Autowired
private PasswordEncoder passwordEncoder;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
System.out.println("username :"+username);
// 模拟一个用户,替代数据库获取逻辑
MyUser user = new MyUser();
user.setUserName(username);
user.setPassword(this.passwordEncoder.encode("123456"));
// 输出加密后的密码
System.out.println(user.getPassword());
return new User(username, user.getPassword(), user.isEnabled(),
user.isAccountNonExpired(), user.isCredentialsNonExpired(),
user.isAccountNonLocked(), AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
}
}
package cc.mrbird.security.browser;
import cc.mrbird.handler.MyAuthenticationFailureHandler;
import cc.mrbird.handler.MyAuthenticationSucessHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private MyAuthenticationSucessHandler authenticationSucessHandler;
@Autowired
private MyAuthenticationFailureHandler authenticationFailureHandler;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin() // 表单登录
// http.httpBasic() // HTTP Basic
.loginPage("/authentication/require") // 登录跳转 URL
.loginProcessingUrl("/login") // 处理表单登录 URL
.successHandler(authenticationSucessHandler) // 处理登录成功
.failureHandler(authenticationFailureHandler) // 处理登录失败
.and()
.authorizeRequests() // 授权配置
.antMatchers("/authentication/require", "/login.html").permitAll() // 登录跳转 URL 无需认证
.anyRequest() // 所有请求
.authenticated() // 都需要认证
.and().csrf().disable();
}
}
2-1、单点登录授权模式选择授权码模式。
2、Client(客户端)
客户端配置(必须与oauth服务配置一致)
security.oauth2.client.client-id
指定OAuth2 client ID
security.oauth2.client.client-secret
指定OAuth2 client secret. 默认是一个随机的secret
security.oauth2.client.user-authorization-uri
用户跳转去获取access token的URI
security.oauth2.client.access-token-uri
指定获取access token的URI
security.oauth2.resource.jwt.key-uri
JWT token的URI. 当key为公钥时,或者value不指定时指定
2、AuthorizationServer ( 服务中心 )
2-1、AuthorizationServerConfigurerAdapter
package cc.mrbird.sso.server.config;
import cc.mrbird.sso.server.service.UserDetailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
/**
* @author MrBird
*/
@Configuration
@EnableAuthorizationServer
public class SsoAuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
private UserDetailService userDetailService;
@Bean
public TokenStore jwtTokenStore() {
return new JwtTokenStore(jwtAccessTokenConverter());
}
@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter() {
JwtAccessTokenConverter accessTokenConverter = new JwtAccessTokenConverter();
accessTokenConverter.setSigningKey("test_key");//秘钥
return accessTokenConverter;
}
//Client和AuthorizationServer配置一致
// clients.inMemory()
// .withClient("app-a") //与客户端配置security.oauth2.client.client-id一致
// .secret(passwordEncoder.encode("app-a-1234")) //与客户端security.oauth2.client.client-secret配置一致
// .authorizedGrantTypes("refresh_token","authorization_code") //刷新授权码,必须这样写
// .accessTokenValiditySeconds(3600) //授权码有效时间,时间越短越安全
// .scopes("all") //允许授权范围
// .autoApprove(true)
// .redirectUris("http://127.0.0.1:9090/app1/login") //登录地址(本案例采用默认登录地址,可以自己配)
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("app-a")
.secret(passwordEncoder.encode("app-a-1234"))
.authorizedGrantTypes("refresh_token","authorization_code")
.accessTokenValiditySeconds(3600)
.scopes("all")
.autoApprove(true)
.redirectUris("http://127.0.0.1:9090/app1/login")
.and()
.withClient("app-b")
.secret(passwordEncoder.encode("app-b-1234"))
.authorizedGrantTypes("refresh_token","authorization_code")
.accessTokenValiditySeconds(7200)
.scopes("all")
.autoApprove(true)
.redirectUris("http://127.0.0.1:9091/app2/login");
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints.tokenStore(jwtTokenStore())
.accessTokenConverter(jwtAccessTokenConverter())
.userDetailsService(userDetailService);
}
@Override
public void configure(AuthorizationServerSecurityConfigurer security) {
security.tokenKeyAccess("isAuthenticated()"); // 获取密钥需要身份认证
}
}
2-2、WebSecurityConfigurerAdapter :spring security的默认http配置,可以配置HttpSecurity,包括formLogin,antMatcher,hasRole ,本案例不考虑太多
package cc.mrbird.sso.server.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
/**
* @author MrBird
*/
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin() //表单登录
.and()
.authorizeRequests()
.anyRequest()
.authenticated();//所有请求必须在登录后才可以访问
}
}