1、springboot项目引入依赖
org.springframework.boot
spring-boot-starter-security
org.springframework.security.oauth
spring-security-oauth2
2.5.2.RELEASE
org.springframework.security
spring-security-jwt
1.1.1.RELEASE
io.jsonwebtoken
jjwt
0.9.1
2、新建WebSecurityConfig类
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
public PasswordEncoder passwordEncoder() {
//密码为明文方式
//return NoOpPasswordEncoder.getInstance();
return new BCryptPasswordEncoder();
}
//配置安全拦截机制
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/r/**").authenticated()//访问/r开始的请求需要认证通过
.anyRequest().permitAll()//其它请求全部放行
.and()
.formLogin().successForwardUrl("/login-success");//登录成功跳转到/login-success
http.logout().logoutUrl("/logout");//退出地址
}
}
3、新建AuthorizationServer类
@Configuration
@EnableAuthorizationServer
public class AuthorizationServer extends AuthorizationServerConfigurerAdapter {
@Resource(name="authorizationServerTokenServicesCustom")
private AuthorizationServerTokenServices authorizationServerTokenServices;
@Autowired
private AuthenticationManager authenticationManager;
@Resource
private DataSource dataSource;
@Autowired
private PasswordEncoder passwordEncoder;
@Bean
public ClientDetailsService jdbcClientDetailsService() {
JdbcClientDetailsService clientDetailsService = new JdbcClientDetailsService(dataSource);
clientDetailsService.setPasswordEncoder(passwordEncoder);
return clientDetailsService;
}
//客户端详情服务
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.withClientDetails(jdbcClientDetailsService());
}
//令牌端点的访问配置
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints
.authenticationManager(authenticationManager)//认证管理器
.tokenServices(authorizationServerTokenServices)//令牌管理服务
.allowedTokenEndpointRequestMethods(HttpMethod.POST);
}
//令牌端点的安全配置
@Override
public void configure(AuthorizationServerSecurityConfigurer security){
security
.tokenKeyAccess("permitAll()") //oauth/token_key是公开
.checkTokenAccess("permitAll()") //oauth/check_token公开
.allowFormAuthenticationForClients() //表单认证(申请令牌)
;
}
}
4、新建TokenConfig类
@Configuration
public class TokenConfig {
//密钥
private String SIGNING_KEY = “test”;
@Autowired
TokenStore tokenStore;
@Autowired
private JwtAccessTokenConverter accessTokenConverter;
@Bean
public TokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey(SIGNING_KEY);
return converter;
}
//令牌管理服务
@Bean(name="authorizationServerTokenServicesCustom")
public AuthorizationServerTokenServices tokenService() {
DefaultTokenServices service=new DefaultTokenServices();
service.setSupportRefreshToken(true);//支持刷新令牌
service.setTokenStore(tokenStore);//令牌存储策略
TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
tokenEnhancerChain.setTokenEnhancers(Arrays.asList(accessTokenConverter));
service.setTokenEnhancer(tokenEnhancerChain);
service.setAccessTokenValiditySeconds(7200); // 令牌默认有效期2小时
service.setRefreshTokenValiditySeconds(259200); // 刷新令牌默认有效期3天
return service;
}
}
5、新建UserDetailsServiceImpl类
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
private SysUserService sysUserService;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
SysUser user = sysUserService.findByName(username);
if (user == null) {
return null;
}
String[] authorities = {"test"};
Set<String> permissions = sysUserService.findPermissions(username);
//List<GrantedAuthority> grantedAuthorities = permissions.stream().map(GrantedAuthorityImpl::new).collect(Collectors.toList());
String passwd = user.getPassword();
user.setPassword(null);
String jsonstr = JSON.toJSONString(user);
UserDetails userDetails = User.withUsername(jsonstr).password(passwd).authorities(authorities).build();
return userDetails;
}
}
6、微服务集成资源管理
引入依赖:
org.springframework.boot
spring-boot-starter-security
org.springframework.security.oauth
spring-security-oauth2
2.5.2.RELEASE
新建ResouceServerConfig:
@Configuration
@EnableResourceServer
@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)
public class ResouceServerConfig extends ResourceServerConfigurerAdapter {
//资源服务标识
public static final String RESOURCE_ID = "rid";
@Autowired
TokenStore tokenStore;
@Autowired
private MyAccessDeniedHandler myAccessDeniedHandler;
@Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources.resourceId(RESOURCE_ID)//资源 id
.tokenStore(tokenStore)
.accessDeniedHandler(myAccessDeniedHandler)
.stateless(true);
}
@Override
public void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/r/**","/api/drs-api/v1/workflow/**").authenticated()//请求必须认证通过
.anyRequest().permitAll() //其余的全部放行
;
}
}
新建TokenConfig:
@Configuration
public class TokenConfig {
//jwt签名密钥,与认证服务保持一致
private String SIGNING_KEY = "test";
@Bean
public TokenStore tokenStore() {
//JWT令牌存储方案
return new JwtTokenStore(accessTokenConverter());
}
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey(SIGNING_KEY);
return converter;
}
}
新建MyAccessDeniedHandler:
@Component
public class MyAccessDeniedHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException {
//设置响应状态码
httpServletResponse.setStatus(HttpServletResponse.SC_FORBIDDEN);
httpServletResponse.setHeader(“Content-Type”, “application/json;charset=utf-8”);
PrintWriter writer = httpServletResponse.getWriter();
writer.write(“{“status”:“error”,“msg”:“权限不足,请联系管理员”}”);
writer.flush();
writer.close();
}
}