当前位置:   article > 正文

java通过Annotation配置权限_annotation 权限

annotation 权限

(1)创建一个Annotation类,该类用来作为一个Annotation提供给其他类使用,类似于@Resource

  1. package org.lxp.auth;
  2. import java.lang.annotation.Retention;
  3. import java.lang.annotation.RetentionPolicy;
  4. /**
  5. * 只要在Controller上增加了这个方法的类,都需要进行权限的控制
  6. * @author Administrator
  7. *
  8. */
  9. @Retention(RetentionPolicy.RUNTIME)
  10. public @interface AuthClass {
  11. /**
  12. * 如果value为admin就表示这个类只能超级管理员访问
  13. * 如果value为login表示这个类中的方法,某些可能为相应的角色可以访问
  14. * @return
  15. */
  16. public String value() default "admin";
  17. }
(2)定义新的Annotation,这个Annotation用来控制用户可以访问哪个方法

  1. package org.lxp.auth;
  2. import java.lang.annotation.Retention;
  3. import java.lang.annotation.RetentionPolicy;
  4. /**
  5. * 用来确定哪些方法由哪些角色访问
  6. * 属性有一个role:如果role的值为base表示这个方法可以被所有的登录用户访问
  7. * 如果为ROLE_PUBLISH表示只能为文章发布人员访问
  8. * 如果某个方法中没有加入AuthMethod就表示该方法只能被管理员所访问
  9. * @author Administrator
  10. *
  11. */
  12. @Retention(RetentionPolicy.RUNTIME)
  13. public @interface AuthMethod {
  14. public String role() default "base";
  15. }




(2)在Action上增加相应的访问控制,Annotation形式如下:

  1. @Controller
  2. @RequestMapping("/admin/user")
  3. @AuthClass("login")//登陆用户都可以访问
  4. public class UserController {
  5. <span style="white-space:pre"> </span>private IUserService userService;
  6. <span style="white-space:pre"> </span>public IUserService getUserService() {
  7. <span style="white-space:pre"> </span>return userService;
  8. <span style="white-space:pre"> </span>}
  9. <span style="white-space:pre"> </span>@Inject
  10. <span style="white-space:pre"> </span>public void setUserService(IUserService userService) {
  11. <span style="white-space:pre"> </span>this.userService = userService;
  12. <span style="white-space:pre"> </span>}
  13. <span style="font-family: Arial, Helvetica, sans-serif;"> </span>
  14. <span style="white-space:pre"></span><pre name="code" class="java"><span style="white-space:pre"> </span>//没有写@AuthMethod这个注解,也就是<span style="font-family: Arial, Helvetica, sans-serif;">只能是管理员才能够访问</span>
@RequestMapping("/users")//
public String list(Model model) {
model.addAttribute("datas",userService.findUser());
return "user/list";
}

 
<span style="white-space:pre">	</span>//增加@AuthMethod这个注解,默认值是base,也就是所有的登陆用户都可以访问
  1. <span style="white-space:pre"> </span>@RequestMapping(value="/updateSelf",method=RequestMethod.GET)
  2. <span style="white-space:pre"> </span>@AuthMethod
  3. <span style="white-space:pre"> </span>public String updateSelf(Model model,HttpSession session) {
  4. <span style="white-space:pre"> </span>User u = (User)session.getAttribute("loginUser");
  5. <span style="white-space:pre"> </span>model.addAttribute(new UserDto(u));
  6. <span style="white-space:pre"> </span>return "user/updateSelf";
  7. <span style="white-space:pre"> </span>}
  8. <span style="white-space:pre"> </span>
  9. <span style="white-space:pre"> </span>@RequestMapping(value="/updateSelf",method=RequestMethod.POST)
  10. <span style="white-space:pre"> </span>@AuthMethod
  11. <span style="white-space:pre"> </span>public String updateSelf(@Valid UserDto userDto,BindingResult br,Model model,HttpSession session) {
  12. <span style="white-space:pre"> </span>if(br.hasErrors()) {
  13. <span style="white-space:pre"> </span>return "user/updateSelf";
  14. <span style="white-space:pre"> </span>}
  15. <span style="white-space:pre"> </span>User ou = userService.load(userDto.getId());
  16. <span style="white-space:pre"> </span>ou.setNickname(userDto.getNickname());
  17. <span style="white-space:pre"> </span>ou.setPhone(userDto.getPhone());
  18. <span style="white-space:pre"> </span>ou.setEmail(userDto.getEmail());
  19. <span style="white-space:pre"> </span>userService.update(ou);
  20. <span style="white-space:pre"> </span>session.setAttribute("loginUser", ou);
  21. <span style="white-space:pre"> </span>return "redirect:/admin/user/showSelf";
  22. <span style="white-space:pre"> </span>}

  1. @Controller
  2. @AuthClass("login")
  3. @RequestMapping("/admin/topic")
  4. public class TopicController {
  5. <pre name="code" class="java"><span style="white-space:pre"> </span>//增加role属性,说明只有文章发布人员可以访问
@RequestMapping("/add")@AuthMethod(role="ROLE_PUBLISH")public void add() {}@RequestMapping("/delete")@AuthMethod(role="ROLE_PUBLISH")public void delete() {}@RequestMapping("/audit")@AuthMethod(role="ROLE_AUDIT")public void audit() {}}

 (3)基于方法的控制,当用户通过某个形式能够确定它访问的是哪个类的哪个方法,如访问/admin/topic/delete那么就会访问到TopicController的delete方法,这样的形式我们可以考虑在过滤器中获取用户访问的类的方法,然后看该方法有没有用户角色相对应的权限 

①首先通过反射,获取到注解名称:使用该注解的方法这养一个键值对

  1. package org.lxp.auth;
  2. import java.io.File;
  3. import java.io.FilenameFilter;
  4. import java.lang.reflect.Method;
  5. import java.util.HashMap;
  6. import java.util.HashSet;
  7. import java.util.Map;
  8. import java.util.Set;
  9. public class AuthUtil {
  10. /**
  11. * 初始化系统的角色所访问的功能信息
  12. * @return
  13. */
  14. @SuppressWarnings({ "rawtypes", "unchecked" })
  15. public static Map<String,Set<String>> initAuth(String pname) {
  16. try {
  17. //存储的是如:{ROLE_PUBLISH:[org.lxp.controller.TopicController.delete,org.lxp.controller.TopicController.add],
  18. //base:[org.lxp.controller.AdminController.list,org.lxp.controller.AdminController.update]}
  19. Map<String,Set<String>> auths = new HashMap<String, Set<String>>();
  20. String[] ps = getClassByPackage(pname);
  21. for(String p:ps) {
  22. //得到所有类的名称,如org.lxp.controller.AdminController
  23. String pc = pname+"."+p.substring(0,p.lastIndexOf(".class"));
  24. //得到了类的class对象
  25. Class clz = Class.forName(pc);
  26. //判断哪些类有@AuthClass这个注解
  27. if(!clz.isAnnotationPresent(AuthClass.class)) continue;
  28. // System.out.println(pc);
  29. //获取每个类中的方法,以此确定哪些角色可以访问哪些方法
  30. Method[] ms = clz.getDeclaredMethods();
  31. /*
  32. * 遍历method来判断每个method上面是否存在相应的AuthMethd
  33. * 如果存在就直接将这个方法存储到auths中,如果不存在就不存储
  34. * 不存储就意味着该方法只能由超级管理员访问
  35. */
  36. for(Method m:ms) {
  37. if(!m.isAnnotationPresent(AuthMethod.class)) continue;
  38. //如果存在就要获取这个Annotation
  39. AuthMethod am = m.getAnnotation(AuthMethod.class);
  40. String role = am.role();
  41. Set<String> actions = auths.get(role);
  42. if(actions==null) {
  43. actions = new HashSet<String>();
  44. auths.put(role, actions);
  45. }
  46. //将那个包里面的哪个类中的哪个方法加入到actions中
  47. actions.add(pc+"."+m.getName());
  48. }
  49. }
  50. return auths;
  51. } catch (ClassNotFoundException e) {
  52. e.printStackTrace();
  53. }
  54. return null;
  55. }
  56. /**
  57. * 根据包获取所有的类
  58. * @param pname
  59. * @return
  60. */
  61. private static String[] getClassByPackage(String pname) {
  62. String pr = pname.replace(".", "/");
  63. //能够得到包的绝对路径,如:d:/workspases/cms-web/target/classes/org/lxp/controller
  64. String pp = AuthUtil.class.getClassLoader().getResource(pr).getPath();
  65. File file = new File(pp);
  66. String[] fs = file.list(new FilenameFilter() {
  67. @Override
  68. public boolean accept(File dir, String name) {
  69. if(name.endsWith(".class")) return true;//返回所有的类
  70. return false;
  71. }
  72. });
  73. return fs;
  74. }
  75. public static void main(String[] args) {
  76. System.out.println(initAuth("org.lxp.controller"));
  77. }
  78. }
②何时对上面的角色信息进行加载呢?项目初始化的时候就应该加载好,这样效率会比较高

  1. package org.lxp.web;
  2. import java.util.Map;
  3. import java.util.Set;
  4. import javax.servlet.ServletConfig;
  5. import javax.servlet.ServletException;
  6. import javax.servlet.http.HttpServlet;
  7. import org.lxp.auth.AuthUtil;
  8. import org.springframework.web.context.WebApplicationContext;
  9. import org.springframework.web.context.support.WebApplicationContextUtils;
  10. public class InitServlet extends HttpServlet {
  11. private static final long serialVersionUID = 1L;
  12. private static WebApplicationContext wc;
  13. @Override
  14. public void init(ServletConfig config) throws ServletException {
  15. super.init(config);
  16. //初始化spring的工厂,可以在任意的servlet或者filter中使用spring的工厂
  17. wc = WebApplicationContextUtils.getWebApplicationContext(this.getServletContext());
  18. //初始化权限信息
  19. Map<String,Set<String>> auths = AuthUtil.initAuth("org.lxp.controller");//后面可以扩展为多个
  20. this.getServletContext().setAttribute("allAuths", auths);
  21. System.out.println("------------------------系统初始化成功:"+auths+"-----------------------------");
  22. }
  23. public static WebApplicationContext getWc() {
  24. return wc;
  25. }
  26. }
③修改web.xml,增加一个servlet,在启动的时候就会将相应角色可以访问哪些方法加载好了

  1. <servlet>
  2. <servlet-name>initServlet</servlet-name>
  3. <servlet-class>org.lxp.web.InitServlet</servlet-class>
  4. <load-on-startup>1</load-on-startup><!-- 初始化的时候就执行 -->
  5. </servlet>

(4)在用户登录之后就应该对用户的权限进行判断,登录后将该用户所有的权限保存到session中

  1. @RequestMapping(value="/login",method=RequestMethod.POST)
  2. public String login(String username,String password,String checkcode,Model model,HttpSession session) {
  3. String cc = (String)session.getAttribute("cc");
  4. if(!cc.equals(checkcode)) {
  5. model.addAttribute("error","验证码出错,请重新输入");
  6. return "admin/login";
  7. }
  8. User loginUser = userService.login(username, password);
  9. session.setAttribute("loginUser", loginUser);
  10. List<Role> rs = userService.listUserRoles(loginUser.getId());
  11. boolean isAdmin = isAdmin(rs);
  12. session.setAttribute("isAdmin", isAdmin);
  13. if(!isAdmin)
  14. session.setAttribute("allActions", getAllActions(rs, session));
  15. session.removeAttribute("cc");
  16. return "redirect:/admin";
  17. }
  18. @SuppressWarnings("unchecked")
  19. private Set<String> getAllActions(List<Role> rs,HttpSession session) {
  20. Set<String> actions = new HashSet<String>();
  21. Map<String,Set<String>> allAuths = (Map<String,Set<String>>)session.getServletContext().getAttribute("allAuths");
  22. actions.addAll(allAuths.get("base"));//所有登录用户都可以访问的权限
  23. for(Role r:rs) {
  24. if(r.getRoleType()==RoleType.ROLE_ADMIN) continue;
  25. actions.addAll(allAuths.get(r.getRoleType().name()));
  26. }
  27. return actions;
  28. }
  29. private boolean isAdmin(List<Role> rs) {
  30. for(Role r:rs) {
  31. if(r.getRoleType()==RoleType.ROLE_ADMIN) return true;
  32. }
  33. return false;
  34. }
(5)访问该功能之前要判断当前session(上面存储的allSessions)中的值能否访问该功能,使用spring的拦截器

  1. package org.lxp.web;
  2. import java.util.Set;
  3. import javax.servlet.http.HttpServletRequest;
  4. import javax.servlet.http.HttpServletResponse;
  5. import javax.servlet.http.HttpSession;
  6. import org.lxp.cms.model.CmsException;
  7. import org.lxp.cms.model.User;
  8. import org.springframework.web.method.HandlerMethod;
  9. import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
  10. public class AuthInterceptor extends HandlerInterceptorAdapter {
  11. @SuppressWarnings("unchecked")
  12. @Override
  13. //提交给任何一个对象之前执行
  14. public boolean preHandle(HttpServletRequest request,
  15. HttpServletResponse response, Object handler) throws Exception {
  16. HttpSession session = request.getSession();
  17. HandlerMethod hm = (HandlerMethod)handler;//可通过这个对象获取值
  18. System.out.println(hm.getBean().getClass.getName()+"."+hm.getMethod().getName());
  19. User user = (User)session.getAttribute("loginUser");
  20. if(user==null) {
  21. response.sendRedirect(request.getContextPath()+"/login");
  22. } else {
  23. boolean isAdmin = (Boolean)session.getAttribute("isAdmin");
  24. if(!isAdmin) {
  25. //不是超级管理人员,就需要判断是否有权限访问某些功能
  26. Set<String> actions = (Set<String>)session.getAttribute("allActions");
  27. String aname = hm.getBean().getClass().getName()+"."+hm.getMethod().getName();
  28. if(!actions.contains(aname)) throw new CmsException("没有权限访问该功能");
  29. }
  30. }
  31. return super.preHandle(request, response, handler);
  32. }
  33. /*
  34. //提交给视图执行
  35. public boolean postHandle(HttpServletRequest request,
  36. HttpServletResponse response, Object handler,ModelAndView modelAndView) throws Exception{
  37. super.postHandle(request, response, handler, modelAndView);
  38. }
  39. //提交完成后用来释放资源
  40. public boolean afterCompletion(HttpServletRequest request,
  41. HttpServletResponse response, Object handler,Exception ex) throws Exception{
  42. super.afterCompletion(request, response, handler, ex);
  43. }*/
  44. }
②在cms-servlet.xml中配置拦截器,启动了之后,上面的程序
System.out.println(hm.getBean().getClass.getName()+"."+hm.getMethod().getName());
首先会输出访问的方法名:如org.lxp.controller.UserController.list

  1. <span style="white-space:pre"> </span><mvc:interceptors>
  2. <!-- 这个地方配置的是全局拦截器 --><!-- <bean></bean>-->
  3. <mvc:interceptor><!-- 配置某一写方法,使用拦截器 -->
  4. <mvc:mapping path="/admin/**"/>
  5. <bean class="org.lxp.web.AuthInterceptor"/>
  6. </mvc:interceptor>
  7. </mvc:interceptors>

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Guff_9hys/article/detail/955883
推荐阅读
相关标签
  

闽ICP备14008679号