すでに有名なApacheの四郎は、認証証明書のネットの形に似たJavaを知らないしません。基本的には同じで、認証と認可の方針による.NETコア。すべてのアクセス権の社会的行動がシミュレートされた個人または組織があるのでもちろん、私は、問題ではありませんわかりません。
簡単な話から権限のこのシリーズは、主に史郎、春のセキュリティ、JWT、OAuth2.0およびその他のカスタム権利ポリシーに関連します。
この章では、基本的な原則を説明し、史郎を使用する方法を、この章では、次のインフラストラクチャを使用しています:
- jdk1.8 +
- 春ブーツ2.1.6
- アイデア2018.1
1春ブーツ迅速な統合史郎例
まず、我々はいくつかの実際のコードを下げては春ブーツ史郎を統合する方法を示します。このサンプル・コードは、データベース関連の知識であることに使用されていない、このコードは、主に使用されます。
- shiro
- thymeeaf
この例では、サイト管理者ユーザのパスワードを実証123456人のユーザーがパスワードログのウェブサイトをユーザー名、史郎認証、アクセス認可権限リストの後に、権限の使用を示しています。
1.1新しい春のブートMavenのサンプルプロジェクト
- ファイル>新規>プロジェクト、以下の図を選択
Spring Initializr
して、[次へ]をクリックします次 - フィル
GroupId
(パッケージ名)、Artifact
(プロジェクト名)にすることができます。次のクリック
のgroupId = com.fishpro
たartifactId =史郎 - 選択は異なり
Spring Web Starter
、フロントダニを。 - プロジェクト名が設定されています
spring-boot-study-shiro
。
1.2依存導入のpom.xml
このコードは、主に使用されます。
- shiro
- thymeeaf
pom.xmlに次のコードを追加すること
<?xml version="1.0" encoding="UTF-8"?>
<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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.fishpro</groupId>
<artifactId>shiro</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>shiro</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!--shiro 1.4.0 thymeleaf-extras-shiro 2.0.0 组合-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.4.0</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0</version>
</dependency>
<!--shiro for thymeleaf 生效需要加入 spring boot 2.x 请使用 2.0.0 版本 否则使用 1.2.1版本-->
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.0.0</version>
</dependency>
<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>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
1.3設定application.yml
この例では、デフォルトの設定を使用して、コンフィギュレーションはapplication.ymlに史郎では必要ありません。我々application.propertiesは、application.yml(習慣)を変更し、デフォルトのポートを変更しました
server:
port: 8086
1.4カスタムレルム・フィールドは、カスタム認証および承認を実装してあるUserRealm
SRC /メイン/ javaの/ COM /でのjava / fishpro /四郎/コンフィグ(設定は、 新しいパッケージ名である)新しいUserRealm.javaファイルの
あるUserRealmは、ユーザーのログイン認証は、このようなコアに実装され、安全なデータソースで、ユーザーそのような許可は、コードのコメントを参照して具体的には、実装されています
- 書き直した
doGetAuthenticationInfo
認証用のユーザー名とパスワードを、と返すSimpleAuthenticationInfo
オブジェクトを。* 史郎は、セキュリティのフレームワークですので注意してください、達成するために自分自身を与えるために必要な証明書の具体的な識別は、実際には、認証は、我々が実現を所有する最高のビジネスロジックであること。 - 書き換えられた
doGetAuthorizationInfo
現在のユーザの許可を実装するために、と返すSimpleAuthorizationInfo
オブジェクトの権限は、現在のユーザーのアクセス権リストに知られているビジネスシステムからデータベースを照会試合を行うために時間を使うために、現在のセッションで書くことであることをメモして、マッチは成功しています明示的な許可が成功し、試合は許可されていないを表す失敗します
//定义一个实体对象用于存储用户信息
public class UserDO {
private Integer id;
private String userName;//就是 shiro 中的身份,系统中唯一的存在
private String password; //就是 shiro 中的证明
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
パッケージの設定(ない新しい設定上の)下にあるUserRealmを確立
package com.fishpro.shiro.config;
import com.fishpro.shiro.domain.UserDO;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import java.security.Principal;
import java.util.*;
/**
* 用户领域 重写了 AuthorizingRealm ,AuthorizingRealm(授权) 其实是继承了 AuthenticatingRealm(认证)
* 所在在这里只要继承 AuthorizingRealm(授权),主要实现 授权和认证的方法重写
* 1.doGetAuthenticationInfo 重写认证
* 2.doGetAuthorizationInfo 重写授权
* */
public class UserRealm extends AuthorizingRealm {
/**
* doGetAuthenticationInfo 重写认证
* @param authenticationToken token
* @return 返回认证信息实体(好看身份和证明) AuthenticationInfo
* */
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
String username=(String)authenticationToken.getPrincipal();//身份 例如 用户名
Map<String ,Object> map=new HashMap<>(16);
map.put("username",username);
String password =new String((char[]) authenticationToken.getCredentials());//证明 例如 密码
//对身份+证明的数据认证 这里模拟了一个数据源
//如果是数据库 那么这里应该调用数据库判断用户名密码是否正确
if(!"admin".equals(username) || !"123456".equals(password)){
throw new IncorrectCredentialsException("账号或密码不正确");
}
//认证通过
UserDO user=new UserDO();
user.setId(1);//假设用户ID=1
user.setUserName(username);
user.setPassword(password);
//建立一个 SimpleAuthenticationInfo 认证模块,包括了身份】证明等信息
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, password, getName());
return info;
}
/**
* 重写授权 doGetAuthorizationInfo 返回 授权信息对象 AuthorizationInfo
* @param principalCollection 身份信息
* @return 返回 授权信息对象 AuthorizationInfo
* */
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
UserDO userDO = (UserDO)principalCollection.getPrimaryPrincipal();
Integer userId= userDO.getId();//转成 user 对象
//授权 新建一个授权模块 SimpleAuthorizationInfo 把 权限赋值给当前的用户
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//设置当前会话拥有的角色 实际场景根据业务来如从数据库获取角色列表
Set<String> roles=new HashSet<>();
roles.add("admin");
roles.add("finance");
info.setRoles(roles);
//设置当前会话可以拥有的权限 实际场景根据业务来如从数据库获取角色列表下的权限列表
Set<String> permissions=new HashSet<>();
permissions.add("system:article:article");
permissions.add("system:article:add");
permissions.add("system:article:edit");
permissions.add("system:article:remove");
permissions.add("system:article:batchRemove");
info.setStringPermissions(permissions);
return info;
}
}
ログイン認証が実現1.6史郎
ここでは、メインディスプレイlogin.htmlととLoginControllerです
新しいファイルリソース/テンプレート/ login.htmlとは、ロジックはjqueryのを使用して実装されたログインページを意味し、
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>使用 shiro 登录页面</title>
</head>
<body>
<div>
<input id="userName" name="userName" value="">
</div>
<div>
<input id="password" name="password" value="">
</div>
<div>
<input type="button" id="btnSave" value="登录">
</div>
<script src="https://cdn.bootcss.com/jquery/1.11.3/jquery.js"></script>
<script>
$(function() {
$("#btnSave").click(function () {
var username=$("#userName").val();
var password=$("#password").val();
$.ajax({
cache: true,
type: "POST",
url: "/login",
data: "userName=" + username + "&password=" + password,
dataType: "json",
async: false,
error: function (request) {
console.log("Connection error");
},
success: function (data) {
if (data.status == 0) {
window.location = "/index";
return false;
} else {
alert(data.message);
}
}
});
});
});
</script>
</body>
</html>
1.7史郎コントローラ層の認証方法を実装
これは、この機能を達成するためにページ数を増やす必要があります
1.7.1成功したジャンプのランディングページの後にリソース/テンプレート/ index.htmlを
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>通过登录验证后跳转到此页面</title>
</head>
<body>
通过登录验证后跳转到此页面
<div>
<a href="/article">前往文章页面</a>
</div>
<div>
<a href="/setting">前往设置页面</a>
</div>
</body>
</html>
ページにアクセスすることを許可1.7.2リソース/テンプレート/ article.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>必须获取 app:article 授权</title>
</head>
<body>
必须获取 app:article 授权 才会显示
</body>
</html>
1.7.3リソース/テンプレート/ setting.html不正アクセスページ
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>必须获取 app:setting 授权 </title>
</head>
<body>
必须获取 app:setting 授权 才会显示
</body>
</html>
1.7.4リソース/テンプレート/エラー/ 403.html不正統一ブローページ
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>403 没有授权</title>
</head>
<body>
你访问的页面没有授权
</body>
</html>
1.7.5コントローラ/ UserController.javaコントローラ層法
ソースコードとして
- 入力する記事:記事:メソッドの記事は許可アプリを必要とします
- 設定:入力するために、アクセス許可の設定に必要なアプリの設定方法
@Controller
public class UserController {
//shiro 认证成功后默认跳转页面
@GetMapping("/index")
public String index(){
return "index";
}
@GetMapping("/403")
public String err403(){
return "403";
}
/**
* 根据权限授权使用注解 @RequiresPermissions
* */
@GetMapping("/article")
@RequiresPermissions("app:article:article")
public String article(){
return "article";
}
/**
* 根据权限授权使用注解 @RequiresPermissions
* */
@GetMapping("/setting")
@RequiresPermissions("app:setting:setting")
public String setting(){
return "setting";
}
@GetMapping("/login")
public String login(){
return "login";
}
@PostMapping("/login")
@ResponseBody
public Object loginsubmit(@RequestParam String userName,@RequestParam String password){
Map<String,Object> map=new HashMap<>();
//把身份 useName 和 证明 password 封装成对象 UsernamePasswordToken
UsernamePasswordToken token=new UsernamePasswordToken(userName,password);
//获取当前的 subject
Subject subject = SecurityUtils.getSubject();
try{
subject.login(token);
map.put("status",0);
map.put("message","登录成功");
return map;
}catch (AuthenticationException e){
map.put("status",1);
map.put("message","用户名或密码错误");
return map;
}
}
}
1.8史郎は、フロントページの承認を達成します
私たちはあなたにもJSP、FreeMarkerのおよび他のエンジンを使用することができ、テンプレートエンジンのフロントエンドとしてThymeleafを使用しました。史郎は、私があなたのホームに次のコードを使用し、中Thymeleafで非常に良い使用することができました
四郎は、さまざまな方法の使用を許可することができます
|方法|注意事項|例|
| --- | --- | --- |
| | @RequiresAuthentication | @RequiresAuthentication |ログインを確認し
、私が覚えていれば| | @RequiresUserを||
|訪問者かどうか| @RequiresGuest | @RequiresGuest |
| @RequiresRoles | | @RequiresRoles( "ADMIN")|保有文字かどうか
| @RequiresPermissions( "パーマ" | @RequiresPermissions |権限を持っています |)
なぜ私のコメントは反映されませんか?
コントローラのアプローチを承認し史郎注釈を使用するには、ShiroConfigに次のコードを追加する必要があります
/**
* 开启shiro aop注解支持 如@RequiresRoles,@RequiresPermissions
* 使用代理方式;所以需要开启代码支持;
* @param securityManager
* @return
*/
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
1.9ログアウト/ログアウト
償却のログアウト方法件名を呼び出します
@GetMapping("/logout")
String logout(HttpSession session, SessionStatus sessionStatus, Model model) {
//会员中心退出登录 当使用这两属性session属性退出
session.removeAttribute("userData");
sessionStatus.setComplete();
SecurityUtils.getSubject().logout();
return "redirect:/login";
}
1.10問題
@RequiresPermissions
無効な注意
ノートは無効で、コメントに来ていなかった、基本的な問題は、AOPのインターセプタがShiroConfig構成の割り当てを増やす必要があります
- ときにメソッドを呼び出すために許可されていません春のブート史郎
@RequiresPermissions
たときに権限は発生しません
@RequiresPermissions
発効以来、なぜそれがすでに理にかなってエラーがでログインしますが、許可メソッド本体を持っていない、あなたは/ 403ページ魚にジャンプする必要があります。
また、このエラーを傍受する方法は存在しないはずです。これに例外処理の春ブーツグローバルでは、あなたがこの例外を捕捉するための例外メカニズムをキャッチする必要があり、前にも言ったorg.apache.shiro.authz.UnauthorizedException
し、その後の中央ください。
@ControllerAdvice(annotations = Controller.class)
public class MyExceptionController {
private static final Logger logger= LoggerFactory.getLogger(MyExceptionController.class);
public static final String DEFAULT_ERROR_VIEW = "error";
@ExceptionHandler(value = UnauthorizedException.class)//处理访问方法时权限不足问题
public String defaultErrorHandler(HttpServletRequest req, Exception e) {
return "error/403";
}
}
- 史郎:hasPermissionタグはthymeleafに質問で有効になりません。
四郎:thymeleafでhasPermissionラベルアプリケーション、元のサードパーティコントロールの導入には、例えば、サポートされていない場合、それは、二つのフレームに関連します。
/**
* ShiroDialect,为了在thymeleaf里使用shiro的标签的bean
* @return
*/
@Bean
public ShiroDialect shiroDialect() {
return new ShiroDialect();
}
- 時には間違ったorg.springframework.beans.factory.BeanCreationExceptionを返します。エラーの名前でBeanを作成する「shiroDialect」
これは、サードパーティ製のプラグインのcom.github.theborakompanioniと春のブートバージョンの互換性の問題でなければなりません。私はthymeleaf春ブーツ2.xの使用バージョン2.0.0を追加する必要があるため、次のバージョンでは、SHIROを反映するように変更しました
<!--shiro 1.4.0 thymeleaf-extras-shiro 2.0.0 组合-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.4.0</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0</version>
</dependency>
<!--shiro for thymeleaf 生效需要加入 spring boot 2.x 请使用 2.0.0 版本 否则使用 1.2.1版本-->
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.0.0</version>
</dependency>