#重构项目,整理maven父子结构,改善认证及资源服务器配置,增加注释更清晰好理解~
#2019.11.4 新增自定义返回token数据;
#2019.11.5 新增自定义登陆及授权页面(没有前后端分离,其实这种小页面也没必要分离出去)
1.项目结构
服务名 | 端口号 | 备注 |
auth | 8082 | 认证服务器 |
mechant | 8081 | 资源服务器 |
zuul | 80 | 网关(这版可用可不用) |
2.省略各模块结构生成及eureka等配置~
3.配置认证服务器
(1) 首先配置springsecurity,其实他底层是很多filter组成,顺序是请求先到他这里进行校验,然后在到oauth2进行资源认证
/**
* @author: gaoyang
* @Description: 身份认证拦截
*/
@Order(1)
@Configuration
//注解权限拦截
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
UserDetailsServiceConfig userDetailsServiceConfig;
//认证服务器需配合Security使用
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
//websecurity用户密码和认证服务器客户端密码都需要加密算法
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//验证用户权限
auth.userDetailsService(userDetailsServiceConfig);
//也可以在内存中创建用户并为密码加密
// auth.inMemoryAuthentication()
// .withUser("user").password(passwordEncoder().encode("123")).roles("USER")
// .and()
// .withUser("admin").password(passwordEncoder().encode("123")).roles("ADMIN");
}
//uri权限拦截,生产可以设置为启动动态读取数据库,具体百度
@Override
protected void configure(HttpSecurity http) throws Exception {
http
//此处不要禁止formLogin,code模式测试需要开启表单登陆,并且/oauth/token不要放开或放入下面ignoring,因为获取token首先需要登陆状态
.formLogin()
.and()
.csrf().disable()
.authorizeRequests().antMatchers("/test").permitAll()
.and()
.authorizeRequests().anyRequest().authenticated();
}
//设置不拦截资源服务器的认证请求
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/oauth/check_token");
}
}
(2)这里的UserDetailsServiceConfig就是去校验登陆用户,可以写测试使用内存或者数据库方式读取用户信息(我这里写死了账号为user,密码为123)
@Component
public class UserDetailsServiceConfig implements UserDetailsService {
@Autowired
private PasswordEncoder passwordEncoder;
//生产环境使用数据库进行验证
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
if (!username.equals("user")) {
throw new AcceptPendingException();
}
return new User(username, passwordEncoder.encode("123"),
AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER"));
}
}
(3)配置认证服务器(详见注释)
/**
* @author: gaoyang
* @Description:认证服务器配置
*/
@Order(2)
@EnableAuthorizationServer
@Configuration
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
AuthenticationManager authenticationManager;
@Autowired
BCryptPasswordEncoder bCryptPasswordEncoder;
@Autowired
UserDetailsServiceConfig myUserDetailsService;
//为了测试客户端与凭证存储在内存(生产应该用数据库来存储,oauth有标准数据库模板)
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("client1-code") // cli