APIセキュリティー・マンデート
アクセス制御:
1、ACL:アクセスコントロールリストは、直接、各ユーザーの認証に、彼は何にアクセスすることができます。シンプルの開発が、ユーザーは、各正規ユーザに多くの、多くの問題です。
2、RBAC:役割ベースのアクセス制御。ロール認可するには、ユーザーの役割に与えられました。認証シンプル、トラブルが発生しました。
ACLを使って下の許可フィールドの識別にユーザー権限テーブルを追加し、簡単なアクセス制御を実現しています。
プロジェクトコードの構造:
データベース、ユーザーテーブル:
二つのデータの挿入
Userクラス:
/ ** * <P> *ユーザー * </ P> * * @Author リー・ヤン * @since 2019年10月26日 * / @データ パブリック クラスユーザー実装Serializableを{ プライベート 静的 最終 長い serialVersionUIDの= 1L ; プライベートロングID。 プライベート文字列名; プライベート文字列のユーザ名。 プライベート文字列のパスワード。 プライベート文字列の権限。 public boolean hasPermission(String method){ boolean result = false; if(StringUtils.equalsIgnoreCase("get",method)){ //如果是get请求,判断user的permissions是否有r result = StringUtils.contains(permissions,"r"); }else { //是否有w权限 result = StringUtils.contains(permissions,"w"); } return result; } }
拦截
用拦截器进行拦截,因为授权要在审计之后,审计就是拦截器,如果权限控制用过滤器,就会在审计之前执行
/** * 基于ACL访问控制的权限拦截器 * 在审计之后执行 */ @Component public class AclInterceptor extends HandlerInterceptorAdapter { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.err.println("+++授权+++" +4); boolean result = true; //从request拿用户信息 User user = (User)request.getAttribute("user"); if(user == null){ //未认证 response.setContentType("text/plain"); response.setStatus(HttpStatus.UNAUTHORIZED.value()); response.getWriter().write("未认证"); result = false; }else { //判断用户是否有权限访问 if(!user.hasPermission(request.getMethod())){ //没权限 response.setContentType("text/plain"); response.setStatus(HttpStatus.FORBIDDEN.value()); response.getWriter().write("未授权"); result = false; } } return result; } }
webconfig配置:
@Configuration public class SecurityConfig implements WebMvcConfigurer { //审计日志 @Autowired private AuditLogInterceptor auditLogInterceptor; //授权 @Autowired private AclInterceptor aclInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(auditLogInterceptor);//.addPathPatterns();//先add的先执行,默认所有请求都拦截 registry.addInterceptor(aclInterceptor); } }
正常的访问:
控制台打印,可以看到,限流、认证、审计、授权几个过滤器拦截器,是预期的执行顺序
2019-12-08 20:52:33.857 INFO 50060 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2019-12-08 20:52:33.857 INFO 50060 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2019-12-08 20:52:33.863 INFO 50060 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 6 ms
++++流控++++ 1
++++认证++++ 2
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@a3f8551] was not registered for synchronization because synchronization is not active
JDBC Connection [com.mysql.jdbc.JDBC4Connection@1914b4d] will not be managed by Spring
==> Preparing: SELECT id,password,permissions,name,username FROM user WHERE (username = ?)
==> Parameters: lhy(String)
<== Columns: id, password, permissions, name, username
<== Row: 1, 123, r, 阳仔, lhy
<== Total: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@a3f8551]
+++审计+++3
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@230e191f] was not registered for synchronization because synchronization is not active
JDBC Connection [com.mysql.jdbc.JDBC4Connection@1914b4d] will not be managed by Spring
==> Preparing: INSERT INTO audit_log ( path, method, create_time, username ) VALUES ( ?, ?, ?, ? )
==> Parameters: /users/1(String), GET(String), 2019-12-08 20:52:34.143(Timestamp), lhy(String)
+++审计拦截器,insert+++
<== Updates: 1
+++授权+++4
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@230e191f]
Controller getUser,id=1
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@771b52e5] was not registered for synchronization because synchronization is not active
JDBC Connection [com.mysql.jdbc.JDBC4Connection@1914b4d] will not be managed by Spring
==> Preparing: SELECT id,password,permissions,name,username FROM user WHERE id=?
==> Parameters: 1(Long)
<== Columns: id, password, permissions, name, username
<== Row: 1, 123, r, 阳仔, lhy
<== Total: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@771b52e5]
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@776808b4] was not registered for synchronization because synchronization is not active
JDBC Connection [com.mysql.jdbc.JDBC4Connection@1914b4d] will not be managed by Spring
==> Preparing: SELECT id,path,method,create_time,update_time,username,status FROM audit_log WHERE id=?
==> Parameters: 144(Long)
<== Columns: id, path, method, create_time, update_time, username, status
<== Row: 144, /users/1, GET, 2019-12-08 20:52:34.0, null, lhy, null
<== Total: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@776808b4]
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@359aa106] was not registered for synchronization because synchronization is not active
JDBC Connection [com.mysql.jdbc.JDBC4Connection@1914b4d] will not be managed by Spring
==> Preparing: UPDATE audit_log SET path=?, method=?, create_time=?, update_time=?, username=?, status=? WHERE id=?
==> Parameters: /users/1(String), GET(String), 2019-12-08 20:52:34.0(Timestamp), 2019-12-08 20:52:34.302(Timestamp), lhy(String), 200(Integer), 144(Long)
<== Updates: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@359aa106]
+++审计拦截器,update+++
未授权的访问:
审计日志
代码:https://github.com/lhy1234/springcloud-security/tree/master/nb-user-api
++++++++++++++++++分割线++++++++++++++++++
小结
用ACL访问控制列表+拦截器实现了一个简单的权限控制