ユーザーが権限を認証したことを確認し、能力を検証することを許可し、それによって、ユーザは、このような一般的なようなことを行うことができるかどうかを決定することです:ユーザーが役割を持っていることを確認してください。またはきめ細かいユーザーがリソースに対するアクセス権を持っているかどうかを確認します。
:::先端注意
注意:許可は、認証の基礎に基づいています
:::
次の3つの方法の認可の
- プログラミング方法:そのような現在の対象者が時間を決定するために、このアプローチは、実際に家の方法を入力したかどうかを決定する権限を持っている場合は使用など。
- 方法ノート:メソッドに入る前に検証するためのメソッドのパーミッションアノテーションを追加します。
- JSPタグ方式:ユーザー権限によって提供さ史郎JSPタグを直接ダイレクトアクセスURLの実施形態からの要求が承認を必要としない場合、表示に従って操作ボタン等かどうかを決定します。
認証ステップ
1.アプローチに@RequirePermissionコメントを追加承認が必要です
3点に注意することは、アノテーションを使用する場合:①自分自身をコメント、我々は、コメント②注釈付きクラスを定義する必要があり、注釈を有効にする方法についてメソッドやクラス③にコメントします
例えば、私は、クエリのリストに追加され@RequiresPermissions("user:list")
、それ以外の場合はスローされます、それはこの方法では、ユーザがアクセスできるllistのアクセス権を持っているユーザーが必要であることを意味し、注釈UnauthorizedException
例外を。
2.春 - 史郎ファイル内のプロキシクラスの分析ノートを設定します
<!-- 开启aop,对类代理 -->
<aop:config proxy-target-class="true"></aop:config>
<!-- 开启shiro注解支持 -->
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager" />
</bean>
:::warning 注意:
私はあるUserRealm認証情報で、この時間は、現在のユーザが任意の権限を持っていないことを意味しますが、私は実際に訪問したときに、この方法は、通常の訪問することができ、空である、コントローラにこのメソッドを追加しました。。。。Baiduの大法によって質問に対する答えを見つけます:
私たちは、コメント史郎リーSpringのAOPを実現している許可されていることを知っています。プログラムが自動的に起動するとスキャンがノートを見つけたときに、自動的に認証コードを注入し、クラスを注釈を付けました。すなわち、制御コードは、注釈付きクラスを見つけることができますスキャンする最初のフレームを作る必要があり、承認を注入されるべきです。
spring.xml
<context:component-scan base-package="cn.edu.neusoft" >
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
春-mvc.xml
<context:component-scan base-package="cn.edu.neusoft" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
applicationContext.xmlをにおける当社のSrpingプロジェクトは、一般的にコントローラをスキャンされません、施行されたコントローラの認可から書かれたノートを作ることができなくなります。したがって、正しいアプローチはspringmvc構成プロファイルに置くことである。このようなコントローラはコメントで許可することができます。
しかし、問題は、上記の構成・コントローラーによってコメントによって認可されているが、サービスはまだ承認されているコメントすることはできません。けれども、我々はコントローラからの許可をコントロールしている場合、内部コールのサービス層は、もはや、許可することができます
しかし、だけでなく、リモートSOAP呼び出しのために、あなたはサービスの許可を制御する必要がある内部コールに加えて、このようなサービスコントローラ層としての例外が、あります。コントローラおよびサービスを制御するために、同じ時間、同じ方法で、我々は同じ効果を達成するために、applicationContext.xmlをで同様の構成を設定することができます。
:::
史郎例外処理の設定
SpringMVCは、デフォルトの例外処理メカニズムを持っているので、ここでは、有効にする特殊なラフ史郎例外ハンドラを定義する必要があるかどうか、この例外は、このページにリダイレクトさnopermisson場合権限
<!--shiro权限异常处理-->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop key="org.apache.shiro.authz.UnauthorizedException">redirect:/admin/system/nopermission</prop>
</props>
</property>
</bean>
:::先端はここでは無視し、AJAXを使用していませんでした。
ここでの最初のステップは、私がいない要求が傍受されていたコントローラに要求する前に、バックnopermissionに応じ、このページには、しかし、AJAXとそこにはありませんが、AJAXリクエストを使用しています、完全であるが、問題が発生しました自動的に受け入れることは非常に難しい、ページにジャンプ。。。
これは、アドレス指定されています。。(日が最終的に解決して下さい):
参考記事:https://blog.csdn.net/catoop/article/details/69210140
原理は、他のコントローラを継承することができ、統一されたプロセスを通じてBaseControllerにあり、そしてジャンプのためのJSONページに、私たちはAjaxの判断が可能との契約を行う必要があります。
BaseControllerコード:
/**
* @author Chen
* @create 2019-05-02 19:26
*/
public abstract class BaseController {
/**
* 权限异常
*/
@ExceptionHandler({ UnauthorizedException.class, AuthorizationException.class })
public String authorizationException(HttpServletRequest request, HttpServletResponse response) {
if (WebUtilsPro.isAjaxRequest(request)) {
// 输出JSON
Map<String,Objectmap = new HashMap<>();
map.put("type", "error");
map.put("msg", "无权限");
writeJson(map, response);
return null;
} else {
return "redirect:/system/403";
}
}
/**
* 输出JSON
*
* @param response
* @author SHANHY
* @create 2017年4月4日
*/
private void writeJson(Map<String,Objectmap, HttpServletResponse response) {
PrintWriter out = null;
try {
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json; charset=utf-8");
out = response.getWriter();
//这里用了一个阿里的fastjson,直接添加一下依赖即可
out.write(String.valueOf(new JSONObject(map)));
} catch (IOException e) {
e.printStackTrace();
} finally {
if (out != null) {
out.close();
}
}
}
}
WebUtilsProコード:
package cn.edu.neusoft.common;
import javax.servlet.http.HttpServletRequest;
/**
* @author Chen
* @create 2019-05-02 19:27
*/
public class WebUtilsPro {
/**
* 是否是Ajax请求
*
* @param request
* @return
* @author SHANHY
* @create 2017年4月4日
*/
public static boolean isAjaxRequest(HttpServletRequest request) {
String requestedWith = request.getHeader("x-requested-with");
if (requestedWith != null && requestedWith.equalsIgnoreCase("XMLHttpRequest")) {
return true;
} else {
return false;
}
}
}
そして、このBaseController OKを継承します。
:::
4.ロード権利表現
:::先端説明:
私たちは、権限をマークされているメソッドの数についてはコメントし、ユーザーがアクセス権を持っている必要があり、ユーザーはレルムに史郎を指示する権限を持っている必要があり、非常に多くの方法は確かにデータベースに保存されます私たちは一つ一つがデータベースに追加されて行くことはできません。
のは、データベース:(権利表現と権限名に格納されたデータベースへの注釈のプロパティを取得することで追加してみましょう)
史郎が私たちにカスタム注釈権限の名前を提供していないので、私たちはカスタマイズので名前に許可を得るためのコメントがデータベースに追加しました。
:::
PermissionController:
/**
* @author Chen
* @create 2019-05-01 20:28
*/
@Controller
@RequestMapping("admin/permission")
public class PermissionController {
@Autowired
private PermissionService permissionService;
//请求映射处理映射器
//springmvc在启动时候将所有贴有请求映射标签:RequestMapper方法收集起来封装到该对象中
@Autowired
private RequestMappingHandlerMapping rmhm;
@ResponseBody
@RequestMapping("reload")
public Map<String,Object> reload(){
Map<String,Object> map = new HashMap<String, Object>();
//将系统中所有权限表达式加载进入数据库
//0:从数据库中查询出所有权限表达式,然后对比,如果已经存在了,跳过,不存在添加
List<String> resourcesList = permissionService.getAllResources();
//1:获取controller中所有带有@RequestMapper标签的方法
Map<RequestMappingInfo, HandlerMethod> handlerMethods = rmhm.getHandlerMethods();
Collection<HandlerMethod> methods = handlerMethods.values();
for (HandlerMethod method : methods) {
//2:遍历所有方法,判断当前方法是否贴有@RequiresPermissions权限控制标签
RequiresPermissions anno = method.getMethodAnnotation(RequiresPermissions.class);
if(anno != null){
//3:如果有,解析得到权限表达式,封装成Permission对象保存到Permission表中
//权限表达式
String resource = anno.value()[0];
//去除重复的
if(resourcesList.contains(resource)){
continue;
}
Permission p = new Permission();
p.setResource(resource);
//设置权限名称
p.setName(method.getMethodAnnotation(PermissionName.class).value());
//保存
permissionService.addPermission(p);
}
}
map.put("type","success");
map.put("msg","加载成功!");
return map;
}
}
カテゴリPermissionNameノート
package cn.edu.neusoft.realm;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author Chen
* @create 2019-05-01 20:20
* 自定义权限名称注解
*/
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface PermissionName {
String value();
}
私達はちょうどデータベースへのアクセス権をロードするパスを指定する要求にコメントしたいです。
@RequiresPermissions("user:delete")
@PermissionName("用户删除")
public Map<String,Object> deleteUser(@RequestParam(required = true) Long id){
······
5.統合データベース認証
ここでは、史郎へのアクセス権を持っている役割が既に登録されているかどうかを判断するために彼に言った、対応する権利の役割を置くことができます
doGetAuthorizationInfoあるUserRealmクラスを変更する方法:
/**
* @author Chen
* @create 2019-04-30 15:27
*/
public class UserRealm extends AuthorizingRealm {
@Setter
private UserService userService;
@Setter
private RoleService roleService;
@Setter
private PermissionService permissionService;
@Override
public String getName() {
return "UserRealm";
}
/**
* 授权
*
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
User user = (User) principalCollection.getPrimaryPrincipal();
List<String> permissions = new ArrayList<String>();
List<String> roles = new ArrayList<String>();
if ("admin".equals(user.getUsername())){
//让超级管理员拥有所有权限
permissions.add("*:*");
//查询所有角色
roles = roleService.getRoleByUserId(user.getId());
}else {
//根据用户ID查询该用户具有的角色
roles = roleService.getRoleByUserId(user.getId());
//根据用户ID查询该用户具有的权限
permissions = permissionService.getAllPermissionsByUserId(user.getId());
}
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.addStringPermissions(permissions);
info.addRoles(roles);
return info;
}
/**
* 认证
*
* @param token
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//从token中获取登录的用户名, 查询数据库返回用户信息
String username = (String) token.getPrincipal();
User user = userService.getUserByUsername(username);
if (user == null) {
return null;
}
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, user.getPassword(), getName());
return info;
}
}
春shiro.xmlに対応するサービスを注入することを忘れないでください。
ここでは、マルチテーブルのクエリのユーザID情報と許可情報のクエリの役割に応じて使用し、偶然にブラッシュアップし、必要下のリンクをクリックしてください:
印象づけるために、対応するSQL文で:
<select id="getAllPermissionsByUserId" parameterType="Long" resultType="String">
select resource from user u
join user_role ur on u.id = ur.user_id
join role_permission rp on ur.role_id = rp.role_id
join permission p on rp.permission_id = p.id
where u.id = #{id}
</select>
<mapper namespace="cn.edu.neusoft.dao.RoleDao">
<select id="getRoleByUserId" resultType="String" parameterType="Long">
select sn from role r
join user_role u on r.id = u.role_id where user_id = #{id}
</select>
ここでは資格はそれを完了するために備えています。