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

项目配置

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

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
          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保护你的应用,可以分为简易的分为三个步骤

  • 配置资源服务器
  • 配置认证服务器
  • 配置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
@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

spring boot + security oauth2 + redis + mongodb 框架搭建_第1张图片

看到返回的access_token 了吧,再使用这个token作为参数,请求刚才设置的接口地址

spring boot + security oauth2 + redis + mongodb 框架搭建_第2张图片

这里正确的返回了数据,但是如果没有access_token ,我们能不能直接请求接口呢,看看下面的截图

spring boot + security oauth2 + redis + mongodb 框架搭建_第3张图片

提示了错误信息,没有资源权限,实现了我想要的效果

基本上就完成了项目的雏形搭建,项目结构

spring boot + security oauth2 + redis + mongodb 框架搭建_第4张图片

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

你可能感兴趣的:(学习札记,mongodb,redis,spring-boo,security,maven)