项目配置
pom.xml 文件
jar
risk
org.springframework.boot
spring-boot-starter-parent
1.5.6.RELEASE
UTF-8
UTF-8
3.0
1.8
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
test
redis.clients
jedis
org.springframework.data
spring-data-redis
org.springframework.boot
spring-boot-starter-security
org.springframework.security.oauth
spring-security-oauth2
org.springframework.boot
spring-boot-starter-data-mongodb
maven-compiler-plugin
1.8
yml文件配置:
server:
port: 52000
#redis
spring:
redis:
host: localhost
database: 0
port: 16379
password: yczw20170214
timeout: 6000
clientname: sim
pool:
max-idle: 5
min-idle: 0
max-active: 50
max-wait: -1
#mongodb
data:
mongodb:
port: 27017
host: localhost
database: car_device
#log
logging:
level:
org:
springframework: ERROR
#security
security:
oauth2:
resource:
filter-order: 3
redis 配置
package com.risk.config;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
private static Logger logger = Logger.getLogger(RedisConfig.class);
@Value("${spring.redis.database}")
private int database;
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private int port;
@Value("${spring.redis.password}")
private String password;
@Value("${spring.redis.timeout}")
private int timeout;
@Value("${spring.redis.pool.min-idle}")
private int minIdle;
@Value("${spring.redis.pool.max-idle}")
private int maxIdle;
@Value("${spring.redis.pool.max-wait}")
private long maxWaitMillis;
@Value("${spring.redis.clientname}")
private String clientName;
@Bean
public JedisPool redisPoolFactory() {
logger.info("JedisPool注入成功!!");
logger.info("redis地址:" + host);
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMinIdle(minIdle);
jedisPoolConfig.setMaxIdle(maxIdle);
jedisPoolConfig.setMaxWaitMillis(maxWaitMillis);
JedisPool jedisPool = new JedisPool(jedisPoolConfig, host, port, timeout, timeout, password, database, clientName,
false, null, null, null);
return jedisPool;
}
@Bean
public JedisPoolConfig getRedisConfig(){
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxIdle(maxIdle);
config.setMinIdle(minIdle);
config.setMaxWaitMillis(maxWaitMillis);
return config;
}
@Bean
public JedisConnectionFactory getConnectionFactory(){
JedisConnectionFactory factory = new JedisConnectionFactory();
JedisPoolConfig jedisPoolConfig = getRedisConfig();
factory.setPoolConfig(jedisPoolConfig);
//factory.setPassword(password);
factory.setPort(port);
factory.setHostName(host);
factory.setTimeout(timeout);
factory.setPassword(password);
factory.setDatabase(database);
factory.setClientName(clientName);
factory.setUseSsl(false);
logger.info("JedisConnectionFactory bean init success.");
return factory;
}
@Bean
public RedisTemplate, ?> getRedisTemplate(){
RedisTemplate,?> template = new StringRedisTemplate(getConnectionFactory());
return template;
}
}
redis 通用接口类
package com.risk.service;
import java.util.List;
public interface IRedisService {
public boolean set(String key, String value);
public String get(String key);
public boolean expire(String key,long expire);
public boolean setList(String key ,List list);
public List getList(String key,Class clz);
public long lpush(String key,Object obj);
public long rpush(String key,Object obj);
public String lpop(String key);
}
mongodb 配置
package com.risk.config;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.authentication.UserCredentials;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
import com.mongodb.Mongo;
@Configuration
public class MongoConfig {
private static Logger logger = Logger.getLogger(MongoConfig.class);
private String username;
private String password;
@Value("${spring.data.mongodb.database}")
private String database;
@Value("${spring.data.mongodb.host}")
private String host;
@Bean
public MongoDbFactory mongodbFactory(){
logger.info("mongodb注入成功");
logger.info("mongodb地址:" + host);
UserCredentials usercre = new UserCredentials(username,password);
MongoDbFactory db = new SimpleMongoDbFactory(new Mongo(host),database,usercre);
return db;
}
@Bean
public MongoTemplate mongoTemplate() throws Exception {
return new MongoTemplate(mongodbFactory());
}
}
mongodb通用类
package com.risk.service;
import java.util.List;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.index.IndexInfo;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import com.mongodb.WriteResult;
public interface IMongoService<T> {
/**
* 删除所有索引
*/
void dropAllIndexes();
/**
* 获取所有索引
* @return
*/
List getIndexInfo();
/**
* 查询所有
* @return
*/
List findAll();
/**
* 查询总数
* @param query
* @return
*/
long findCount(Query query);
/**
* 分页查询
* @param query 查询条件
* @param skip 当前页
* @param limit 每页数
* @return
*/
List findList(Query query, Integer skip, Integer limit);
/**
* 分页查询
* @param query 查询条件
* @param currPage 当前页
* @param pageSize 每页数
* @return
*/
List findPageList(Query query, Integer currPage, Integer pageSize);
/**
* 查询单条
* @param id 主键
* @return
*/
T findById(String id);
/**
* 查询单条
* @param query
* @return
*/
T findOne(Query query);
/**
* 添加
* @param entity
* @return
*/
T insert(T entity);
/**
* 有责更新、无责添加
* @param entity
* @return
*/
T save(T entity);
/**
* 批量添加
* @param entitys
* @return
*/
List insertBatch(List entitys);
List bulkWrite(List entitys);
void update(Query query, Update update);
void updateBatch(Query query, Update update);
void delete(Query query);
T findAndModify(Query query, Update update);
WriteResult upsert(Query query, Update update, Class entityClass);
WriteResult upsert(Query query, Update update, Class entityClass,String collectionName);
/**
* 聚合运算
* @param aggregation
* @param inputType
* @param outputType
* @return
*/
AggregationResults aggregate(Aggregation aggregation, Class inputType, Class outputType);
}
spring boot 整合redis、mongodb很简单,这里只看代码,具体不详细说明了,重点讲解一下security 的oauth2 的实现及功能
security oauth2
接口对接的场景,A厂家有一套HTTP接口需要提供给B厂家使用,由于是外网环境,所以需要有一套安全机制保障,这个时候oauth2就可以作为一个方案
使用oauth2保护你的应用,可以分为简易的分为三个步骤
前两点是oauth2的主体内容,但前面我已经描述过了,spring security oauth2是建立在spring security基础之上的,所以有一些体系是公用的。
oauth2根据使用场景不同,分成了4种模式
本文重点讲解接口对接中常使用的密码模式(以下简称password模式)和客户端模式(以下简称client模式)。授权码模式使用到了回调地址,是最为复杂的方式,通常网站中经常出现的微博,qq第三方登录,都会采用这个形式。简化模式不常用
我现在要做的事情:
1、用户请求auth,系统返回token,token存在redis中,可以有效的设置token的时效性
2、通过返回的token请求数据接口,系统认证token后,将数据返回给用户,数据来源mongodb
话不多说,看代码吧
一、配置资源服务器
package com.risk.config.oauth;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import com.risk.common.AuthResource;
/**
* oauth 资源服务器
* @author 番茄很忙
*
*/
@Configuration
@EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
@Override
public void configure(ResourceServerSecurityConfigurer resources){
resources.resourceId(AuthResource.RESOURCEID).stateless(true);
}
@Override
public void configure(HttpSecurity http)throws Exception{
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.and().requestMatchers()
.and().anonymous()
.and().authorizeRequests()
.antMatchers("/risk/**").authenticated();//配置security访问控制,必须认证过后才可以访问
//http.authorizeRequests().antMatchers("/risk/**").hasRole("USER");
}
}
二、配置授权服务器
package com.risk.config.oauth;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.oauth2.config.annotation.builders.ClientDetailsServiceBuilder.ClientBuilder;
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.store.redis.RedisTokenStore;
import com.risk.common.AuthResource;
/**
* oauth 授权服务器
* @author 番茄很忙
*
*/
@Configuration
@EnableAuthorizationServer
public class OauthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private AuthenticationManager authenticationManager;
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception{
//配置两个客户端,一个用于password认证一个用于client认证
ClientBuilder clientbuilder = clients.inMemory().withClient("client_1").resourceIds(AuthResource.RESOURCEID);
clientbuilder.authorizedGrantTypes("client_credentials","refresh_token");
clientbuilder.scopes("select");
clientbuilder.authorities("client");
clientbuilder.secret("123456");
ClientBuilder passwordbuilder = clientbuilder.and().withClient("client_2").resourceIds(AuthResource.RESOURCEID);
passwordbuilder.authorizedGrantTypes("password","refresh_token");
passwordbuilder.scopes("select");
passwordbuilder.authorities("client");
passwordbuilder.secret("123456");
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception{
endpoints.allowedTokenEndpointRequestMethods();
endpoints.tokenStore(new RedisTokenStore(redisTemplate.getConnectionFactory())).authenticationManager(authenticationManager);
}
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer)throws Exception{
//允许表单认证
oauthServer.allowFormAuthenticationForClients();
}
}
三、配置spring security
package com.risk.config.oauth;
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.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
/**
* 配置 UserDetailsService ,现在写死,修改 后可以查询数据库mongodb
*/
@Bean
@Override
protected UserDetailsService userDetailsService(){
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
manager.createUser(User.withUsername("user_1").password("123456").authorities("USER").build());
manager.createUser(User.withUsername("user_2").password("123456").authorities("USER").build());
return manager;
}
/**
* 这一步的配置是必不可少的,否则SpringBoot会自动配置一个AuthenticationManager,覆盖掉内存中的用户
*/
@Override
protected void configure(HttpSecurity http)throws Exception{
http.requestMatchers().anyRequest()
.and().authorizeRequests().antMatchers("/oauth/*").permitAll();
//.and().authorizeRequests().antMatchers("/risk/**").hasRole("USER");
}
}
springboot 整合security oauth2 就是这么简单,三个配置
下面我们来写一个controller测试oauth2
package com.risk.controller;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class RiskController {
@GetMapping(value="/risk/{id}")
public String risk(String id){
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
return "risk test"+id;
}
}
使用postman工具发送请求,可以百度下载安装,获取token设置了post请求,浏览器一般的地址请求都是GET
看到返回的access_token 了吧,再使用这个token作为参数,请求刚才设置的接口地址
这里正确的返回了数据,但是如果没有access_token ,我们能不能直接请求接口呢,看看下面的截图
提示了错误信息,没有资源权限,实现了我想要的效果
基本上就完成了项目的雏形搭建,项目结构
redis 、mongodb的具体实现类,请下载源码吧,太多了,不好粘贴出来
项目能正常运行,下载解压即可使用、打包、部署
README.MD文件中有maven的打包教程
代码下载地址:http://download.csdn.net/download/fs_sky/9935990
security oauth2 参考资料:
http://mp.weixin.qq.com/s?__biz=MzAxODcyNjEzNQ==&mid=2247484093&idx=2&sn=4a046dacfd00c982ca1fa942eec3a70a&chksm=9bd0af25aca72633de25cd54fb4a24c9e45b9e17a98a11cd3de94b8e35fda0bb7d6a8e4c406e&mpshare=1&scene=1&srcid=0814CyA1FJifwkDoJUesKzKB#rd