浏览代码

增加oauth2 示例

zhouhao 8 年之前
父节点
当前提交
dede390372

+ 5 - 0
hsweb-examples/hsweb-examples-oauth2/README.md

@@ -0,0 +1,5 @@
+# OAuth2.0 例子
+
+客户端:[hsweb-examples-oauth2-client](hsweb-examples-oauth2-client)
+
+服务端:[hsweb-examples-oauth2-server](hsweb-examples-oauth2-server)

+ 5 - 0
hsweb-examples/hsweb-examples-oauth2/hsweb-examples-oauth2-client/README.md

@@ -0,0 +1,5 @@
+# hsweb OAuth2.0 客户端演示
+
+1. 运行`OAuth2ClientApplication.main`启动项目,启动前先保证[服务端](../hsweb-examples-oauth2-server)已启动
+2. 访问 `http://localhost:8808/login.html?redirect=/test` ,点击使用hsweb登录引导到服务端
+3. 登录成功后会自动跳转到 `http://localhost:8808/test`,显示`admin角色`相关数据则代表运行成功

+ 109 - 0
hsweb-examples/hsweb-examples-oauth2/hsweb-examples-oauth2-client/pom.xml

@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~  Copyright 2016 http://www.hswebframework.org
+  ~
+  ~  Licensed under the Apache License, Version 2.0 (the "License");
+  ~  you may not use this file except in compliance with the License.
+  ~  You may obtain a copy of the License at
+  ~
+  ~        http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~  Unless required by applicable law or agreed to in writing, software
+  ~  distributed under the License is distributed on an "AS IS" BASIS,
+  ~  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~  See the License for the specific language governing permissions and
+  ~  limitations under the License.
+  ~
+  ~
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>hsweb-examples-oauth2</artifactId>
+        <groupId>org.hswebframework.web</groupId>
+        <version>3.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>hsweb-examples-oauth2-client</artifactId>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <version>${spring.boot.version}</version>
+                <configuration>
+                    <mainClass>org.hswebframework.web.example.oauth2.OAuth2ClientApplication</mainClass>
+                    <layout>ZIP</layout>
+                </configuration>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>repackage</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+    <dependencies>
+        <dependency>
+            <groupId>org.codehaus.groovy</groupId>
+            <artifactId>groovy-all</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.h2database</groupId>
+            <artifactId>h2</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>druid</artifactId>
+            <version>1.0.26</version>
+        </dependency>
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-classic</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-jdbc</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-logging</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.hswebframework.web</groupId>
+            <artifactId>hsweb-spring-boot-starter</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <!--<dependency>-->
+            <!--<groupId>org.hswebframework.web</groupId>-->
+            <!--<artifactId>hsweb-system-authorization-starter</artifactId>-->
+            <!--<version>${project.version}</version>-->
+        <!--</dependency>-->
+
+        <dependency>
+            <groupId>org.hswebframework.web</groupId>
+            <artifactId>hsweb-authorization-shiro</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.hswebframework.web</groupId>
+            <artifactId>hsweb-system-oauth2-client-starter</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+    </dependencies>
+</project>

+ 53 - 0
hsweb-examples/hsweb-examples-oauth2/hsweb-examples-oauth2-client/src/main/java/org/hswebframework/web/example/oauth2/IndexController.java

@@ -0,0 +1,53 @@
+/*
+ *  Copyright 2016 http://www.hswebframework.org
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+
+package org.hswebframework.web.example.oauth2;
+
+import org.hswebframework.web.authorization.Authentication;
+import org.hswebframework.web.authorization.annotation.Authorize;
+import org.hswebframework.web.controller.message.ResponseMessage;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * TODO 完成注释
+ *
+ * @author zhouhao
+ */
+@RestController
+@RequestMapping("/")
+public class IndexController {
+
+    @GetMapping
+    public ResponseMessage index(Authentication authentication) {
+        return ResponseMessage.ok(authentication);
+    }
+
+    @GetMapping("/test")
+    @Authorize(role = "admin")
+    public ResponseMessage auth() {
+        return ResponseMessage.ok("admin角色");
+    }
+
+    @GetMapping("/test2")
+    @Authorize(role = "admin2")//此角色应该是不存在的
+    public ResponseMessage auth2() {
+        return ResponseMessage.ok("admin2角色");
+    }
+}

+ 136 - 0
hsweb-examples/hsweb-examples-oauth2/hsweb-examples-oauth2-client/src/main/java/org/hswebframework/web/example/oauth2/OAuth2ClientApplication.java

@@ -0,0 +1,136 @@
+/*
+ *  Copyright 2016 http://www.hswebframework.org
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+
+package org.hswebframework.web.example.oauth2;
+
+import org.hsweb.ezorm.rdb.executor.AbstractJdbcSqlExecutor;
+import org.hsweb.ezorm.rdb.executor.SqlExecutor;
+import org.hswebframework.web.authorization.Authentication;
+import org.hswebframework.web.authorization.AuthenticationManager;
+import org.hswebframework.web.authorization.oauth2.client.OAuth2RequestService;
+import org.hswebframework.web.authorization.oauth2.client.response.OAuth2Response;
+import org.hswebframework.web.authorization.shiro.oauth2sso.OAuth2SSOAuthorizingListener;
+import org.hswebframework.web.commons.entity.factory.EntityFactory;
+import org.hswebframework.web.dao.datasource.DataSourceHolder;
+import org.hswebframework.web.dao.datasource.DatabaseType;
+import org.hswebframework.web.entity.oauth2.client.OAuth2ServerConfigEntity;
+import org.hswebframework.web.service.oauth2.client.OAuth2ServerConfigService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.EnableAspectJAutoProxy;
+import org.springframework.jdbc.datasource.DataSourceUtils;
+
+import javax.sql.DataSource;
+import java.sql.Connection;
+import java.sql.SQLException;
+
+/**
+ * TODO 完成注释
+ *
+ * @author zhouhao
+ */
+@SpringBootApplication
+@Configuration
+@EnableCaching
+@EnableAspectJAutoProxy
+public class OAuth2ClientApplication implements CommandLineRunner {
+
+    public static void main(String[] args) {
+        SpringApplication.run(OAuth2ClientApplication.class);
+    }
+
+    @Bean
+    public AuthenticationManager authenticationManager() {
+        // 由于没有使用用户管理,
+        // 而且暂时没有实现默认的OAuth2相关的权限获取策略,
+        // 所以这里使用通过OAuth2进行获取
+        // 实现类似sso的功能,这里实际上应该将权限信息存储起来
+        return new AuthenticationManager() {
+            @Override
+            public Authentication getByUserId(String userId) {
+                //获取远程的用户权限信息
+                return oAuth2RequestService.create("hsweb-oauth-server")
+                        .byClientCredentials()
+                        .request("oauth2/user-auth-info/" + userId)
+                        .get().onError(OAuth2Response.throwOnError)
+                        .as(Authentication.class);
+            }
+
+            @Override
+            public Authentication sync(Authentication authentication) {
+                //暂时不支持
+                return authentication;
+            }
+        };
+    }
+
+    @Autowired
+    EntityFactory             entityFactory;
+    @Autowired
+    OAuth2ServerConfigService serverConfigService;
+    @Autowired
+    OAuth2RequestService      oAuth2RequestService;
+
+    @Override
+    public void run(String... strings) throws Exception {
+        OAuth2ServerConfigEntity entity = entityFactory.newInstance(OAuth2ServerConfigEntity.class);
+        entity.setId("hsweb-oauth-server");
+        entity.setName("hsweb OAuth2");
+        //可以修改hosts文件改为域名
+        entity.setApiBaseUrl("http://localhost:8080/");
+        entity.setAuthUrl("oauth2/login.html");
+        entity.setAccessTokenUrl("oauth2/token");
+        //和服务端创建的一致
+        entity.setClientId("hsweb_oauth2_example");
+        entity.setClientSecret("hsweb_oauth2_example_secret");
+        entity.setRedirectUri("http://localhost:8808/");
+        //hsweb
+        entity.setProvider("hsweb");
+        entity.setEnabled(true);
+        //add
+        serverConfigService.insert(entity);
+
+        OAuth2SSOAuthorizingListener listener = new OAuth2SSOAuthorizingListener(oAuth2RequestService, entity.getId());
+
+        oAuth2RequestService.registerListener(entity.getId(), listener);
+    }
+
+
+    @Bean
+    @ConditionalOnMissingBean(SqlExecutor.class)
+    public SqlExecutor sqlExecutor(DataSource dataSource) {
+        DataSourceHolder.install(dataSource, DatabaseType.h2);
+        return new AbstractJdbcSqlExecutor() {
+            @Override
+            public Connection getConnection() {
+                return DataSourceUtils.getConnection(dataSource);
+            }
+
+            @Override
+            public void releaseConnection(Connection connection) throws SQLException {
+                DataSourceUtils.releaseConnection(connection, dataSource);
+            }
+        };
+    }
+}

+ 19 - 0
hsweb-examples/hsweb-examples-oauth2/hsweb-examples-oauth2-client/src/main/resources/application.yml

@@ -0,0 +1,19 @@
+
+spring:
+    aop:
+        auto: true
+        proxy-target-class: true
+    datasource:
+       url : jdbc:h2:mem:example-oauth2-client
+       username : sa
+       password :
+       type: com.alibaba.druid.pool.DruidDataSource
+       driver-class-name : org.h2.Driver
+    cache:
+       type: simple
+hsweb:
+    app:
+      name: hsweb-oauth2 客户端示例
+      version: 3.0.0
+server:
+  port: 8808

+ 73 - 0
hsweb-examples/hsweb-examples-oauth2/hsweb-examples-oauth2-client/src/main/resources/static/login.html

@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<!--
+  ~  Copyright 2016 http://www.hswebframework.org
+  ~
+  ~  Licensed under the Apache License, Version 2.0 (the "License");
+  ~  you may not use this file except in compliance with the License.
+  ~  You may obtain a copy of the License at
+  ~
+  ~        http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~  Unless required by applicable law or agreed to in writing, software
+  ~  distributed under the License is distributed on an "AS IS" BASIS,
+  ~  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~  See the License for the specific language governing permissions and
+  ~  limitations under the License.
+  ~
+  ~
+  -->
+
+<html lang="zh-cn">
+<head>
+    <meta charset="UTF-8">
+    <meta http-equiv=Content-Type content="text/html;charset=utf-8">
+    <title>登录</title>
+    <script type="application/javascript" src="//cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>
+
+</head>
+<body>
+<button onclick="doHswebLogin()">使用hsweb登录</button>
+</body>
+</html>
+<script type="text/javascript">
+    function doHswebLogin() {
+        var uri = getRequest()["redirect"];
+        if (!uri) uri = "/";
+        window.open('/oauth2/boot/hsweb-oauth-server?redirect=' + uri);
+        var clientId = "hsweb_oauth2_example";
+//        var api = "http://localhost:8080/oauth2/login.html";
+//        //申请一个state
+//        doAjax("GET", "/oauth2/state", {}, function (e) {
+//            if (e) {
+//                window.open(api + "?client_id=" + clientId + "&response_type=code&state=" + e.result + "&redirect_uri="
+//                    + escape("http://localhost:8808/oauth2/callback/hsweb-oauth-server/?redirect=" + uri))
+//            }
+//        });
+    }
+
+    function getRequest() {
+        var url = location.search; //获取url中"?"符后的字串
+        var theRequest = new Object();
+        if (url.indexOf("?") != -1) {
+            var str = url.substr(1);
+            strs = str.split("&");
+            for (var i = 0; i < strs.length; i++) {
+                theRequest[strs[i].split("=")[0]] = unescape((strs[i].split("=")[1]));
+            }
+        }
+        return theRequest;
+    }
+
+    function doAjax(method, url, data, success, error) {
+        $.ajax({
+            type: method,
+            url: url,
+            data: data,
+            success: success,
+            error: function (e) {
+                error(e.responseJSON);
+            },
+            dataType: "json"
+        });
+    }
+</script>

+ 4 - 0
hsweb-examples/hsweb-examples-oauth2/hsweb-examples-oauth2-server/README.md

@@ -0,0 +1,4 @@
+# hsweb OAuth2.0 服务端演示
+
+1. 运行 `OAuth2ServerApplication.main` 启动项目
+2. 试试运行[客户端](../hsweb-examples-oauth2-client)

+ 107 - 0
hsweb-examples/hsweb-examples-oauth2/hsweb-examples-oauth2-server/pom.xml

@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~  Copyright 2016 http://www.hswebframework.org
+  ~
+  ~  Licensed under the Apache License, Version 2.0 (the "License");
+  ~  you may not use this file except in compliance with the License.
+  ~  You may obtain a copy of the License at
+  ~
+  ~        http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~  Unless required by applicable law or agreed to in writing, software
+  ~  distributed under the License is distributed on an "AS IS" BASIS,
+  ~  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~  See the License for the specific language governing permissions and
+  ~  limitations under the License.
+  ~
+  ~
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>hsweb-examples-oauth2</artifactId>
+        <groupId>org.hswebframework.web</groupId>
+        <version>3.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>hsweb-examples-oauth2-server</artifactId>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <version>${spring.boot.version}</version>
+                <configuration>
+                    <mainClass>org.hswebframework.web.example.oauth2.org.hswebframework.web.example.oauth2.OAuth2ServerApplication</mainClass>
+                    <layout>ZIP</layout>
+                </configuration>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>repackage</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+    <dependencies>
+        <dependency>
+            <groupId>org.codehaus.groovy</groupId>
+            <artifactId>groovy-all</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.h2database</groupId>
+            <artifactId>h2</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>druid</artifactId>
+            <version>1.0.26</version>
+        </dependency>
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-classic</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-jdbc</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-logging</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.hswebframework.web</groupId>
+            <artifactId>hsweb-spring-boot-starter</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.hswebframework.web</groupId>
+            <artifactId>hsweb-system-authorization-starter</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.hswebframework.web</groupId>
+            <artifactId>hsweb-authorization-shiro</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.hswebframework.web</groupId>
+            <artifactId>hsweb-system-oauth2-server-starter</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+    </dependencies>
+</project>

+ 179 - 0
hsweb-examples/hsweb-examples-oauth2/hsweb-examples-oauth2-server/src/main/java/org/hswebframework/web/example/oauth2/OAuth2ServerApplication.java

@@ -0,0 +1,179 @@
+/*
+ *  Copyright 2016 http://www.hswebframework.org
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+
+package org.hswebframework.web.example.oauth2;
+
+import org.hsweb.ezorm.rdb.executor.AbstractJdbcSqlExecutor;
+import org.hsweb.ezorm.rdb.executor.SqlExecutor;
+import org.hswebframework.web.authorization.Permission;
+import org.hswebframework.web.authorization.access.DataAccessConfig;
+import org.hswebframework.web.authorization.oauth2.api.entity.OAuth2ClientEntity;
+import org.hswebframework.web.commons.entity.factory.EntityFactory;
+import org.hswebframework.web.dao.datasource.DataSourceHolder;
+import org.hswebframework.web.dao.datasource.DatabaseType;
+import org.hswebframework.web.dao.oauth2.OAuth2ClientDao;
+import org.hswebframework.web.entity.authorization.*;
+import org.hswebframework.web.entity.authorization.bind.BindPermissionRoleEntity;
+import org.hswebframework.web.entity.authorization.bind.BindRoleUserEntity;
+import org.hswebframework.web.service.authorization.PermissionService;
+import org.hswebframework.web.service.authorization.RoleService;
+import org.hswebframework.web.service.authorization.UserService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.EnableAspectJAutoProxy;
+import org.springframework.jdbc.datasource.DataSourceUtils;
+
+import javax.sql.DataSource;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.Arrays;
+
+/**
+ * TODO 完成注释
+ *
+ * @author zhouhao
+ */
+@SpringBootApplication
+@Configuration
+@EnableCaching
+public class OAuth2ServerApplication implements CommandLineRunner {
+
+    public static void main(String[] args) {
+        SpringApplication.run(OAuth2ServerApplication.class);
+    }
+
+
+    @Autowired
+    UserService       userService;
+    @Autowired
+    RoleService       roleService;
+    @Autowired
+    PermissionService permissionService;
+    @Autowired
+    EntityFactory     entityFactory;
+    @Autowired
+    OAuth2ClientDao   oAuth2ClientDao;
+
+
+    @Override
+    public void run(String... strings) throws Exception {
+        //添加示例数据,实际项目应该在前端进行维护
+        /*
+           ---------------------------------------------
+           ------------------添加权限信息----------------
+           -------------用户名: admin,密码: admin--------
+           -------------角色: admin----------------------
+           -------------权限: admin----------------------
+         */
+        //只能查询自己创建的数据
+        DataAccessEntity accessEntity = new DataAccessEntity();
+        accessEntity.setType(DataAccessConfig.DefaultType.OWN_CREATED);
+        accessEntity.setAction(Permission.ACTION_QUERY);
+
+        //只能修改自己创建的数据
+        DataAccessEntity updateAccessEntity = new DataAccessEntity();
+        updateAccessEntity.setType(DataAccessConfig.DefaultType.OWN_CREATED);
+        updateAccessEntity.setAction(Permission.ACTION_UPDATE);
+        //脚本方式自定义控制
+//        updateAccessEntity.setConfig(JSON.toJSONString(new SimpleScriptDataAccess("" +
+//                "println(id);" +
+//                "println(entity);" +
+//                "println('脚本权限控制');" +
+//                "return true;" +
+//                "","groovy")));
+
+        //password 属性不能读取和修改
+        FieldAccessEntity fieldAccessEntity = new FieldAccessEntity();
+        fieldAccessEntity.setField("password");
+        fieldAccessEntity.setActions(ActionEntity.create(Permission.ACTION_QUERY, Permission.ACTION_UPDATE));
+
+        PermissionEntity permission = entityFactory.newInstance(PermissionEntity.class);
+        permission.setName("测试");
+        permission.setId("test");
+        permission.setStatus((byte) 1);
+        permission.setActions(ActionEntity.create(Permission.ACTION_QUERY, Permission.ACTION_UPDATE));
+        permission.setDataAccess(Arrays.asList(accessEntity, updateAccessEntity));
+        permission.setFieldAccess(Arrays.asList(fieldAccessEntity));
+        permissionService.insert(permission);
+
+        BindPermissionRoleEntity<PermissionRoleEntity> roleEntity = entityFactory.newInstance(BindPermissionRoleEntity.class);
+        SimplePermissionRoleEntity permissionRoleEntity = new SimplePermissionRoleEntity();
+        permissionRoleEntity.setRoleId("admin");
+        permissionRoleEntity.setPermissionId("test");
+        permissionRoleEntity.setActions(Arrays.asList(Permission.ACTION_QUERY, Permission.ACTION_UPDATE));
+        permissionRoleEntity.setDataAccesses(permission.getDataAccess());
+        permissionRoleEntity.setFieldAccesses(permission.getFieldAccess());
+        roleEntity.setId("admin");
+        roleEntity.setName("test");
+        roleEntity.setPermissions(Arrays.asList(permissionRoleEntity));
+        roleService.insert(roleEntity);
+
+        BindRoleUserEntity userEntity = entityFactory.newInstance(BindRoleUserEntity.class);
+        userEntity.setId("admin");
+        userEntity.setName("admin");
+        userEntity.setCreateTimeNow();
+        userEntity.setCreatorId("admin");
+        userEntity.setUsername("admin");
+        userEntity.setPassword("admin");
+        userEntity.setRoles(Arrays.asList("admin"));
+        userService.insert(userEntity);
+
+        /*
+            ------------------------添加OAuth2客户端---------------------
+            ------------------client_id:hsweb_oauth2_example------------
+            ------------------client_secret:hsweb_oauth2_example_secret--
+         */
+        OAuth2ClientEntity clientEntity = entityFactory.newInstance(OAuth2ClientEntity.class);
+
+        clientEntity.setId("hsweb_oauth2_example");
+        clientEntity.setSecret("hsweb_oauth2_example_secret");
+        clientEntity.setOwnerId("admin");
+        clientEntity.setName("测试");
+        clientEntity.setType("test");
+        clientEntity.setCreatorId("admin");
+        // 这里与 hsweb-examples-oauth2-client 的回调地址对应
+        clientEntity.setRedirectUri("http://localhost:8808/oauth2/callback/hsweb");
+        clientEntity.setCreateTime(System.currentTimeMillis());
+        clientEntity.setSupportGrantType(Arrays.asList("*"));
+        oAuth2ClientDao.insert(clientEntity);
+    }
+
+    @Bean
+    @ConditionalOnMissingBean(SqlExecutor.class)
+    public SqlExecutor sqlExecutor(DataSource dataSource) {
+        DataSourceHolder.install(dataSource, DatabaseType.h2);
+        return new AbstractJdbcSqlExecutor() {
+            @Override
+            public Connection getConnection() {
+                return DataSourceUtils.getConnection(dataSource);
+            }
+
+            @Override
+            public void releaseConnection(Connection connection) throws SQLException {
+                DataSourceUtils.releaseConnection(connection, dataSource);
+            }
+        };
+
+    }
+}

+ 16 - 0
hsweb-examples/hsweb-examples-oauth2/hsweb-examples-oauth2-server/src/main/resources/application.yml

@@ -0,0 +1,16 @@
+spring:
+    aop:
+        auto: true
+        proxy-target-class: true
+    datasource:
+       url : jdbc:h2:mem:example-oauth2
+       username : sa
+       password :
+       type: com.alibaba.druid.pool.DruidDataSource
+       driver-class-name : org.h2.Driver
+    cache:
+       type: simple
+hsweb:
+    app:
+      name: hsweb-oauth2示例
+      version: 3.0.0

+ 139 - 0
hsweb-examples/hsweb-examples-oauth2/hsweb-examples-oauth2-server/src/main/resources/static/oauth2/login.html

@@ -0,0 +1,139 @@
+<!DOCTYPE html>
+<!--
+  ~  Copyright 2016 http://www.hswebframework.org
+  ~
+  ~  Licensed under the Apache License, Version 2.0 (the "License");
+  ~  you may not use this file except in compliance with the License.
+  ~  You may obtain a copy of the License at
+  ~
+  ~        http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~  Unless required by applicable law or agreed to in writing, software
+  ~  distributed under the License is distributed on an "AS IS" BASIS,
+  ~  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~  See the License for the specific language governing permissions and
+  ~  limitations under the License.
+  ~
+  ~
+  -->
+
+<html lang="zh-cn">
+<head>
+    <meta charset="UTF-8">
+    <meta http-equiv=Content-Type content="text/html;charset=utf-8">
+    <title>OAuth2授权页面</title>
+    <script type="application/javascript" src="//cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>
+    <link rel="stylesheet" href="//cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
+    <script src="//cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
+    <style type="text/css">
+        .login,.isLogin {
+            width: 500px;
+            margin: auto;
+        }
+    </style>
+</head>
+<body>
+<div class="login">
+    <h2 align="center">用户登录</h2>
+    <div class="input-group">
+        <span class="input-group-addon" id="basic-addon1">用户名</span>
+        <input type="text" id="username" class="form-control" placeholder="username" aria-describedby="basic-addon1">
+    </div>
+    <br>
+    <div class="input-group">
+        <span class="input-group-addon">密<span style="margin-left: 1em"></span>码</span>
+        <input type="password" id="password" class="form-control" placeholder="password" aria-describedby="basic-addon1">
+    </div>
+
+    <div style="width: 100px;margin: 10px auto auto;">
+        <button type="button" onclick="doLogin()" class="btn btn-default">登录</button>
+    </div>
+</div>
+<div class="isLogin">
+    当前已登录: <span class="login-username"></span>
+    <button type="button" onclick="doAuth()" class="btn btn-default">授权</button>
+    <button type="button" onclick="changeUser()" class="btn btn-default">更换用户</button>
+</div>
+</body>
+</html>
+<script type="text/javascript">
+    function getParam(name) {
+        var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
+        var r = window.location.search.substr(1).match(reg);
+        if (r != null) return unescape(r[2]);
+        return null;
+    }
+
+    init();
+    function init() {
+        $(".login").hide();
+        $(".isLogin").hide();
+        doAjax("GET", "/authorize/me", {}, function (d) {
+            $(".login-username").text(d.result.user.username);
+            $(".isLogin").show();
+        }, function (e) {
+            $(".login").show();
+        })
+    }
+    function changeUser() {
+        $(".login").show();
+        $(".isLogin").hide();
+    }
+
+    function doLogin() {
+        var username = $("#username").val();
+        var password = $("#password").val();
+        if ($.trim(username) == "") {
+            $("#username").focus();
+            return;
+        }
+        if ($.trim(password) == "") {
+            $("#password").focus();
+            return;
+        }
+        doAjax("POST", "/authorize/login", {username: username, password: password}, function (e, r) {
+            doAuth();
+        }, function (e) {
+            alert(e.message)
+        })
+    }
+    function doAuth() {
+        var param = getRequest();
+        param.scope = "public";
+        //执行OAuth认证
+        doAjax("GET", "/oauth2/authorize", param, function (e, r) {
+            var redirect = unescape(e.redirectUri);
+            var uri = redirect.indexOf("?") != -1 ? "&" : "?";
+            uri += "code=" + e.code + "&state=" + e.state;
+            window.location.href = (redirect + uri);
+        }, function (e) {
+            alert(e.message);
+        })
+    }
+
+    function getRequest() {
+        var url = location.search; //获取url中"?"符后的字串
+        var theRequest = new Object();
+        if (url.indexOf("?") != -1) {
+            var str = url.substr(1);
+            strs = str.split("&");
+            for (var i = 0; i < strs.length; i++) {
+                theRequest[strs[i].split("=")[0]] = unescape((strs[i].split("=")[1]));
+            }
+        }
+        return theRequest;
+    }
+
+    function doAjax(method, url, data, success, error) {
+        $.ajax({
+            type: method,
+            url: url,
+            data: data,
+            success: success,
+            error: function (e) {
+                error(e.responseJSON);
+            },
+            dataType: "json"
+        });
+    }
+</script>

+ 38 - 0
hsweb-examples/hsweb-examples-oauth2/pom.xml

@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~  Copyright 2016 http://www.hswebframework.org
+  ~
+  ~  Licensed under the Apache License, Version 2.0 (the "License");
+  ~  you may not use this file except in compliance with the License.
+  ~  You may obtain a copy of the License at
+  ~
+  ~        http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~  Unless required by applicable law or agreed to in writing, software
+  ~  distributed under the License is distributed on an "AS IS" BASIS,
+  ~  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~  See the License for the specific language governing permissions and
+  ~  limitations under the License.
+  ~
+  ~
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>hsweb-examples</artifactId>
+        <groupId>org.hswebframework.web</groupId>
+        <version>3.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>hsweb-examples-oauth2</artifactId>
+    <packaging>pom</packaging>
+    <modules>
+        <module>hsweb-examples-oauth2-server</module>
+        <module>hsweb-examples-oauth2-client</module>
+    </modules>
+
+
+</project>

+ 1 - 0
hsweb-examples/pom.xml

@@ -30,6 +30,7 @@
     <packaging>pom</packaging>
     <modules>
         <module>hsweb-examples-simple</module>
+        <module>hsweb-examples-oauth2</module>
     </modules>