spring boot + security oauth2 + redis + mongodb 框架搭建

来源:互联网 发布:淘宝首页添加旺旺 编辑:程序博客网 时间:2024/05/29 19:11

项目配置

  1. spring boot 1.5.6
  2. jedis 2.9
  3. jdk 1.8
  4. mongodb driver 3.4.2

pom.xml 文件

    <packaging>jar</packaging>  <name>risk</name>  <description></description>  <parent>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-parent</artifactId>    <version>1.5.6.RELEASE</version>    <relativePath /> <!-- lookup parent from repository --> </parent>  <properties>    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>    <webVersion>3.0</webVersion>    <java.version>1.8</java.version>  </properties>  <dependencies>    <dependency>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-web</artifactId>    </dependency>    <dependency>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-test</artifactId>        <scope>test</scope>    </dependency>    <dependency>        <groupId>redis.clients</groupId>        <artifactId>jedis</artifactId>    </dependency>    <dependency>         <groupId>org.springframework.data</groupId>         <artifactId>spring-data-redis</artifactId>    </dependency>    <dependency>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-security</artifactId>    </dependency>    <dependency>        <groupId>org.springframework.security.oauth</groupId>        <artifactId>spring-security-oauth2</artifactId>    </dependency>    <dependency>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-data-mongodb</artifactId>    </dependency></dependencies>  <build>    <plugins>      <plugin>        <artifactId>maven-compiler-plugin</artifactId>        <configuration>          <source>1.8</source>          <target>1.8</target>        </configuration>      </plugin>    </plugins>  </build>

yml文件配置:

server:  port: 52000#redisspring:   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#loglogging:    level:     org:      springframework: ERROR#securitysecurity:  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@EnableCachingpublic 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 <T> boolean setList(String key ,List<T> list);      public <T> List<T> getList(String key,Class<T> 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;@Configurationpublic 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<IndexInfo> getIndexInfo();    /**     * 查询所有     * @return     */    List<T> findAll();    /**     * 查询总数     * @param query     * @return     */    long findCount(Query query);    /**     * 分页查询     * @param query 查询条件     * @param skip  当前页     * @param limit 每页数     * @return     */    List<T> findList(Query query, Integer skip, Integer limit);    /**     * 分页查询     * @param query     查询条件     * @param currPage  当前页     * @param pageSize  每页数     * @return     */    List<T> 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<T> insertBatch(List<T> entitys);    List<T> bulkWrite(List<T> 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<T> entityClass);    WriteResult upsert(Query query, Update update, Class<T> entityClass,String collectionName);    /**     * 聚合运算     * @param aggregation     * @param inputType     * @param outputType     * @return     */    <O> AggregationResults<O> aggregate(Aggregation aggregation, Class<T> inputType, Class<O> outputType);}

spring boot 整合redis、mongodb很简单,这里只看代码,具体不详细说明了,重点讲解一下security 的oauth2 的实现及功能


security oauth2
接口对接的场景,A厂家有一套HTTP接口需要提供给B厂家使用,由于是外网环境,所以需要有一套安全机制保障,这个时候oauth2就可以作为一个方案

使用oauth2保护你的应用,可以分为简易的分为三个步骤

  • 配置资源服务器
  • 配置认证服务器
  • 配置spring security

前两点是oauth2的主体内容,但前面我已经描述过了,spring security oauth2是建立在spring security基础之上的,所以有一些体系是公用的。

oauth2根据使用场景不同,分成了4种模式

  • 授权码模式(authorization code)
  • 简化模式(implicit)
  • 密码模式(resource owner password credentials)
  • 客户端模式(client credentials)

本文重点讲解接口对接中常使用的密码模式(以下简称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@EnableResourceServerpublic 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@EnableAuthorizationServerpublic class OauthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {    @Autowired    private RedisTemplate<String, ?> 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@EnableWebSecuritypublic 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;@RestControllerpublic 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