zoukankan      html  css  js  c++  java
  • servlet3.0全注解spring整合shiro

    基本说明

    基于Servlet3.0全注解配置的Spring整合Shiro

    目录

    配置文件

    pom.xml

    <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>
    	<groupId>com.td</groupId>
    	<artifactId>spring-shrio</artifactId>
    	<version>0.0.1-SNAPSHOT</version>
    	<packaging>war</packaging>
    
    	<dependencies>
    		<!-- servlet 3.0 -->
    		<dependency>
    			<groupId>javax.servlet</groupId>
    			<artifactId>javax.servlet-api</artifactId>
    			<version>3.1.0</version>
    			<scope>provided</scope>
    		</dependency>
    		<dependency>
    			<groupId>javax.servlet.jsp</groupId>
    			<artifactId>jsp-api</artifactId>
    			<version>2.2</version>
    			<scope>provided</scope>
    		</dependency>
    		<dependency>
    			<groupId>javax.servlet</groupId>
    			<artifactId>jstl</artifactId>
    			<version>1.2</version>
    		</dependency>
    
    		<!-- spring mvc -->
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-webmvc</artifactId>
    			<version>4.3.14.RELEASE</version>
    		</dependency>
    
    		<!-- shiro -->
    		<dependency>
    			<groupId>org.apache.shiro</groupId>
    			<artifactId>shiro-core</artifactId>
    			<version>1.4.0</version>
    		</dependency>
    		<dependency>
    			<groupId>org.apache.shiro</groupId>
    			<artifactId>shiro-web</artifactId>
    			<version>1.4.0</version>
    		</dependency>
    		<dependency>
    			<groupId>org.apache.shiro</groupId>
    			<artifactId>shiro-spring</artifactId>
    			<version>1.4.0</version>
    		</dependency>
    		<dependency>
    		    <groupId>org.apache.shiro</groupId>
    		    <artifactId>shiro-ehcache</artifactId>
    		    <version>1.4.0</version>
    		</dependency>
    		<dependency><!-- 注意:ehcahe 2.5 EhCacheManager以上使用了单例,创建多次会报错 -->
    		    <groupId>net.sf.ehcache</groupId>
    		    <artifactId>ehcache-core</artifactId>
    		    <version>2.4.8</version>
    		</dependency>
    		
    		<dependency>
    			<groupId>org.apache.commons</groupId>
    			<artifactId>commons-lang3</artifactId>
    			<version>3.5</version>
    		</dependency>
    
    	</dependencies>
    
    	<build>
    		<plugins>
    			<!-- 编译插件 -->
    			<plugin>
    				<groupId>org.apache.maven.plugins</groupId>
    				<artifactId>maven-compiler-plugin</artifactId>
    				<version>3.8.0</version>
    				<configuration>
    					<source>1.8</source>
    					<target>1.8</target>
    				</configuration>
    			</plugin>
    			<!-- web项目插件 -->
    			<plugin>
    				<groupId>org.apache.maven.plugins</groupId>
    				<artifactId>maven-war-plugin</artifactId>
    				<version>3.1.0</version>
    			</plugin>
    			<!-- tomcat7插件 -->
    			<plugin>
    				<groupId>org.apache.tomcat.maven</groupId>
    				<artifactId>tomcat7-maven-plugin</artifactId>
    				<version>2.2</version>
    				<configuration>
    					<port>8888</port>
    					<path>/</path>
    					<uriEncoding>UTF-8</uriEncoding>
    				</configuration>
    			</plugin>
    		</plugins>
    	</build>
    </project>
    

    javax.servlet.ServletContainerInitializer(servlet 3.0配置,容器加载配置)

    com.td.WebServletContainerInitializer
    

    WebServletContainerInitializer.java (相当于web.xml)

    package com.td;
    
    import java.util.EnumSet;
    import java.util.Set;
    
    import javax.servlet.DispatcherType;
    import javax.servlet.FilterRegistration.Dynamic;
    import javax.servlet.ServletContainerInitializer;
    import javax.servlet.ServletContext;
    import javax.servlet.ServletException;
    import javax.servlet.annotation.HandlesTypes;
    
    import org.springframework.web.WebApplicationInitializer;
    import org.springframework.web.filter.DelegatingFilterProxy;
    
    /**
     * web.xml配置文件
     */
    @HandlesTypes(WebApplicationInitializer.class)
    public class WebServletContainerInitializer implements ServletContainerInitializer {
    
    	@Override
    	public void onStartup(Set<Class<?>> c, ServletContext ctx) throws ServletException {
    		
    		// shiro过滤器
    		Dynamic filter = ctx.addFilter("shiroFilter", DelegatingFilterProxy.class);
    		filter.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), true, "/*");
    		filter.setInitParameter("targetFilterLifecycle", "true");
    		
    	}
    
    }
    

    MyWebAppInitializer.java (相当于spring.xml)

    package com.td;
    
    import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
    
    import com.td.configuration.RootConfig;
    import com.td.configuration.WebConfig;
    
    public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    
    	// 父容器
        @Override
        protected Class<?>[] getRootConfigClasses() {
            return new Class<?>[] { RootConfig.class };
        }
    
        // 子容器
        @Override
        protected Class<?>[] getServletConfigClasses() {
            return new Class<?>[] { WebConfig.class };
        }
    
        // 拦截请求配置
        @Override
        protected String[] getServletMappings() {
            return new String[] { "/" };
        }
    }
    

    模拟数据库表(基于角色控制权限)

    Permission.java

    package com.td.enums;
    
    public enum Permission {
    	
    	select("select"),update("update"),delete("delete"),insert("insert");
    	
    	String permissionName;
    	private Permission(String permissionName) {
    		this.permissionName = permissionName;
    	}
    	public String getPermissionName() {
    		return permissionName;
    	}
    	public void setPermissionName(String permissionName) {
    		this.permissionName = permissionName;
    	}
    }
    

    Role.java

    package com.td.enums;
    
    public enum Role {
    
    	//管理员角色有 CRUD权限
    	admin("admin", Permission.select,Permission.update,Permission.delete,Permission.insert),
    	//普通用户只有查看权限
    	user("guest", Permission.select);
    	
    	String roleName;
    	Permission[] permission;
    	Role(String roleName, Permission... permission){
    		this.roleName = roleName;
    		this.permission = permission;
    	}
    	
    	public String getRoleName() {
    		return roleName;
    	}
    	public void setRoleName(String roleName) {
    		this.roleName = roleName;
    	}
    	public Permission[] getPermission() {
    		return permission;
    	}
    	public void setPermission(Permission[] permission) {
    		this.permission = permission;
    	}
    }
    
    

    User.java

    package com.td.enums;
    
    public enum User {
    
    	admin(Role.admin, "tandi", "tandi"),  //管理员账号
    	guest(Role.user, "lisi", "lisi"); //普通用户账号
    
    	Role role;
    	String username;
    	String password;
    
    	User(Role role, String username, String password) {
    		this.role = role;
    		this.username = username;
    		this.password = password;
    	}
    
    	
    	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;
    	}
    
    	public Role getRole() {
    		return role;
    	}
    
    	public void setRole(Role role) {
    		this.role = role;
    	}
    
    }
    
    

    父子容器配置

    RootConfig.java

    package com.td.configuration;
    
    import java.util.HashMap;
    import java.util.Map;
    
    import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
    import org.apache.shiro.web.filter.authc.LogoutFilter;
    import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.ComponentScan.Filter;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.FilterType;
    import org.springframework.stereotype.Controller;
    
    import com.td.filter.UserFormAuthenticationFilter;
    import com.td.realm.UserAuthorizingRealm;
    
    @Configuration
    @ComponentScan(basePackages="com.td",
    includeFilters=@Filter(type=FilterType.ANNOTATION,classes=Controller.class))
    public class RootConfig {
    
    	/** shiro bean */
    	
    //	@Bean
    //	public EhCacheManager ehcacheManager() {
    //		EhCacheManager bean = new EhCacheManager();
    //		bean.setCacheManagerConfigFile("classpath:ehcache.xml");
    //		return bean;
    //	}
    	
    	@Bean
    	public org.apache.shiro.mgt.SecurityManager securityManager(
    			UserAuthorizingRealm userAuthorizingRealm/*, 
    			EhCacheManager ehCacheManager*/) {
    		
    		DefaultWebSecurityManager bean = new DefaultWebSecurityManager();
    		
    		bean.setRealm(userAuthorizingRealm); //自定义realm
    //		bean.setCacheManager(ehCacheManager);
    //		bean.setSessionManager(sessionManager);
    		
    		return bean;
    	}	
    	
    	@Bean
    	public ShiroFilterFactoryBean shiroFilter(org.apache.shiro.mgt.SecurityManager securityManager, 
    			UserFormAuthenticationFilter userFormAuthenticationFilter, 
    			LogoutFilter logoutFilter) {
    		
    		ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
    		
    		bean.setSecurityManager(securityManager);
    		bean.setLoginUrl("/user/login"); //表单登录URL
    		bean.setSuccessUrl("/login_success"); //认证成功跳转到的URL
    		bean.setUnauthorizedUrl("/login"); //受权失败调转到的URL
    		
    		//自定义拦截器
    		Map<String, javax.servlet.Filter> filters = new HashMap<>();
    		filters.put("formFilter", userFormAuthenticationFilter); 
    		filters.put("userLogout", logoutFilter); 
    		bean.setFilters(filters);
    		
    		//url拦截配置
    		Map<String, String> map = new HashMap<>();
    		map.put("/", "anon");
    		map.put("/index", "anon");
    		map.put("/login", "anon"); //登录页面,不能省略该配置
    		map.put("/user/logout", "userLogout"); //登出
    		
    //		map.put("/user/login", "formFilter"); //登录认证
    		map.put("/**", "formFilter");
    		bean.setFilterChainDefinitionMap(map);
    		
    		return bean;
    	}	
    	
    	@Bean
    	public LogoutFilter logoutFilter() {
    		LogoutFilter bean = new LogoutFilter();
    		bean.setRedirectUrl("/login");
    		return bean;
    	}
    	
    
    }
    
    

    WebConfig.java

    package com.td.configuration;
    
    import org.apache.shiro.spring.LifecycleBeanPostProcessor;
    import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
    import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.ComponentScan.Filter;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.DependsOn;
    import org.springframework.context.annotation.FilterType;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.servlet.config.annotation.EnableWebMvc;
    import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
    import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
    
    @Configuration
    @ComponentScan(basePackages="com.td",
    includeFilters=@Filter(type=FilterType.ANNOTATION,classes=Controller.class),useDefaultFilters=false)
    @EnableWebMvc
    public class WebConfig extends WebMvcConfigurerAdapter {
    	
    	//配置视图解析器
    	@Override
    	public void configureViewResolvers(ViewResolverRegistry registry) {
    		registry.jsp("/", ".jsp");
    	}
    	
    	//静态资源配置
        @Override
        public void addResourceHandlers(ResourceHandlerRegistry registry) {
            registry.addResourceHandler("/res/**")
                .addResourceLocations("/img/") 
                .setCachePeriod(31556926);
        }
        
    
    	/**
    	 * 启动 shiro 注解
    	 *  【注意】
    	 *  1. 因为配置的是 父子 容器,所以如果要在@Controller标注的类下使用shiro注解
    	 *  	必须将以下配置配置到子容器中来,否者父容器初始化时只扫描shiro注解而不扫描@Controller
    	 *  	就会出现shiro注解不生效的情况;
    	 *  
    	 *  2.所以如果在@Controller标注的类下使用shiro注解,必须是@Controller和shiro注解同时被扫描才是
    	 * @return
    	 */
    	@Bean
    	public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
    		return new LifecycleBeanPostProcessor();
    	}
    	
    	@Bean
    	@DependsOn("lifecycleBeanPostProcessor")
    	public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
    		DefaultAdvisorAutoProxyCreator bean = new DefaultAdvisorAutoProxyCreator();
    		bean.setProxyTargetClass(true);
    		return bean;
    	}
    
    	@Bean
    	public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(org.apache.shiro.mgt.SecurityManager securityManager) {
    		AuthorizationAttributeSourceAdvisor bean = new AuthorizationAttributeSourceAdvisor();
    		bean.setSecurityManager(securityManager);
    		return bean;
    	}
    	
    }
    
    

    自定义认证受权Reaml

    UserAuthorizingRealm.java

    package com.td.realm;
    
    import org.apache.shiro.authc.AuthenticationException;
    import org.apache.shiro.authc.AuthenticationInfo;
    import org.apache.shiro.authc.AuthenticationToken;
    import org.apache.shiro.authc.IncorrectCredentialsException;
    import org.apache.shiro.authc.SimpleAuthenticationInfo;
    import org.apache.shiro.authc.UnknownAccountException;
    import org.apache.shiro.authc.UsernamePasswordToken;
    import org.apache.shiro.authz.AuthorizationInfo;
    import org.apache.shiro.authz.SimpleAuthorizationInfo;
    import org.apache.shiro.realm.AuthorizingRealm;
    import org.apache.shiro.subject.PrincipalCollection;
    import org.springframework.stereotype.Component;
    
    import com.td.enums.Permission;
    import com.td.enums.User;
    
    @Component
    public class UserAuthorizingRealm extends AuthorizingRealm {
    	
    //	@Autowired
    //	XxxService service;
    
    	/**
    	 * 认证
    	 */
    	@Override
    	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
    		
    		System.out.println("
     ===reaml认证处理===");
    		
    		UsernamePasswordToken upToken = (UsernamePasswordToken)token;
    		String username = upToken.getUsername();
    		String password = new String(upToken.getPassword());
    
    		/** 模拟从数据库根据用户名称获取对应的user */
    		User loginUser = null;
    		if(User.admin.getUsername().equals(username)) {
    			loginUser = User.admin;
    		}else if(User.guest.getUsername().equals(username)) {
    			loginUser = User.guest;
    		}else {
    			throw new UnknownAccountException("认证失败!!!没有改账号。。。。");
    		}
    		
    		System.out.println(username + ":::" + password);
    		//校验密码
    		if(!loginUser.getPassword().equals(password))
    			throw new IncorrectCredentialsException("认证失败!!!密码错误。。。。");
    		
    		//返回认证信息
    		return new SimpleAuthenticationInfo(username, password, getName());
    	}
    
    
    
    	/**
    	 * 受权
    	 * 注意:受权方法是当前用户访问权限资源的时候才会调用的
    	 */
    	@Override
    	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
    		
    		System.out.println("
     ===reaml受权处理===");
    		
    		//获取在认证过程中传入的“主要认证信息”
    		String username = (String) getAvailablePrincipal(principals);
    		
    		/** 模拟从数据库根据用户名称获取对应的user */
    		User loginUser = null;
    		if(User.admin.getUsername().equals(username)) {
    			loginUser = User.admin;
    		}else if(User.guest.getUsername().equals(username)) {
    			loginUser = User.guest;
    		}
    		
    		// 创建受权信息对象
    		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
    		
    		// 设置当前用户的角色
    		System.out.println("当前用户有以下角色");
    		System.out.println("-----" + loginUser.getRole().getRoleName() + "-----");
    		info.addRole(loginUser.getRole().getRoleName()); // amdin 和 guest
    		
    		// 设置当前用户的权限
    		Permission[] permissions = loginUser.getRole().getPermission(); // crud四个权限
    		System.out.println("当前用户有以下权限");
    		for (Permission perm : permissions) {
    			System.out.println("-----" + perm.getPermissionName() + "-----");
    			info.addStringPermission(perm.getPermissionName());
    		}
    		
    		return info;
    	}
    
    
    }
    
    

    登录表单过滤器

    UserFormAuthenticationFilter.java

    package com.td.filter;
    
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    
    import org.apache.commons.lang3.StringUtils;
    import org.apache.shiro.authc.AuthenticationException;
    import org.apache.shiro.authc.AuthenticationToken;
    import org.apache.shiro.authc.IncorrectCredentialsException;
    import org.apache.shiro.authc.UnknownAccountException;
    import org.apache.shiro.authc.UsernamePasswordToken;
    import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
    import org.springframework.stereotype.Component;
    
    @Component
    public class UserFormAuthenticationFilter extends FormAuthenticationFilter {
    
    	@Override
    	protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) {
    		
    		System.out.println("filter拦截了请求,创建token....");
    		
    		//拦截获取登录的账号和密码
    		String username = getUsername(request);
    		String password = getPassword(request);
    		if (password==null){
    			password = "";
    		}
    		
    		//返回UsernamePasswordToken对象
    		return new UsernamePasswordToken(username, password);
    	}
    	
    	//认证成功
    	@Override
    	protected void issueSuccessRedirect(ServletRequest request, ServletResponse response) throws Exception {
    		System.out.println("filter认证成功方法执行...");
    		super.issueSuccessRedirect(request, response);
    	}
    
    
    	//认证失败
    	@Override
    	protected boolean onLoginFailure(AuthenticationToken token,
    			AuthenticationException e, ServletRequest request, ServletResponse response) {
    		
    		System.out.println("filter认证失败方法执行...");
    		
    		String className = e.getClass().getName(), message = "";
    		
    		if (IncorrectCredentialsException.class.getName().equals(className)
    				|| UnknownAccountException.class.getName().equals(className)){
    			message = "用户或密码错误, 请重试.";
    		}
    		else if (e.getMessage() != null && StringUtils.startsWith(e.getMessage(), "msg:")){
    			message = StringUtils.replace(e.getMessage(), "msg:", "");
    		}
    		else{
    			message = "系统出现点问题,请稍后再试!";
    			e.printStackTrace(); // 输出到控制台
    		}
    		
    		System.out.println(className + "::" + message);
            request.setAttribute("shiroLoginFailure", className);
            request.setAttribute("message", message);
    		
            /** 认证失败,交给controller继续处理 */
            return true;
    	}
    	
    }
    
    

    控制器

    PageController.java

    package com.td.controller;
    
    import org.apache.shiro.authz.UnauthorizedException;
    import org.apache.shiro.authz.annotation.RequiresRoles;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    @Controller
    public class PageController {
    
    	@RequestMapping({"/index", "/login", "/"})
    	public String login() {
    		return "login";
    	}
    	
    	/**
    	 * 该方法会来拦截器登录认证失败后执行
    	 * @return
    	 */
    	@RequestMapping({"/user/login"})
    	public String redirectLogin() {
    		/**
    		 * 注意:必须使用重定向
    		 * 原因:
    		 * 	当前程序使用Filter进行拦截登录,如果不是重定向,那么进入服务器之后
    		 * 	Filter就只会执行一次,如果要保证每次登录都经过Filter就需要使用重定向
    		 * 	到登录页面
    		 */
    		System.out.println("登录失败,重定向到登录页面!!!");
    //		return "redirect:/";
    //		return "redirect:/index";
    		return "redirect:/login";
    	}
    	
    	@RequestMapping("/login_success")
    	public String loginSuccess() {
    		return "login_success";
    	}
    	
    	/**
    	 * shiro注解需要shiro配置在子容器才生效
    	 * 1. shiro标签用于控制显示
    	 * 2. @RequiresRoles用于控制有心人用url直接访问
    	 * */
    	@RequiresRoles("admin") 
    //	@RequiresPermissions({"insert"})
    	@RequestMapping("/admin")
    	public String admin() {
    		return "admin";
    	}
    	
    	@ExceptionHandler({UnauthorizedException.class})
    	public String noAccess() {
    		return "no_access";
    	}
    
    }
    
    

    View

    login

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
    <!DOCTYPE html>
    <html>
    <head>
    	<meta charset="UTF-8">
    	<title>登录</title>
    </head>
    <body>
    	<!-- 用户登录认证 -->
    	<form action="user/login" method="post" >
    		用户名称:<input type="text" name="username" /><br>
    		用户密码:<input type="text" name="password" /><br>
    		<input type="submit" value="登录"/>
    	</form>
    </body>
    </html>
    

    login_success

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
    <%@taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
    <!DOCTYPE html>
    <html>
    <head>
    	<meta charset="UTF-8">
    	<title></title>
    </head>
    <body>
    	<!-- -->
    	登录认证成功
        <!-- shiro标签会触发realm的受权方法,有权限才会显示 -->
        <!-- 所以只有当前用户有admin角色才会显示 -->
    	<shiro:hasRole name="admin">
    		<br> <a href="admin">admin页面</a>
    	</shiro:hasRole>
    	
    		<br> <a href="user/logout">登出</a>
    	
    </body>
    </html>
    

    admin (只有admin角色才能访问)

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
    <!DOCTYPE html>
    <html>
    <head>
    	<meta charset="UTF-8">
    	<title></title>
    </head>
    <body>
    	<!-- -->
    	admin》》》》》》》》》》》》》
    	
    </body>
    </html>
    

    no_access (访问到权限不够的资源时会跳转到该页面)

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
    <!DOCTYPE html>
    <html>
    <head>
    	<meta charset="UTF-8">
    	<title></title>
    </head>
    <body>
    	<!-- -->
    	没有权限访问
    </body>
    </html>
    

    运行结果

    管理员用户 (tandi/tandi)

    登录成功后

    访问admin页面

    普通用户(lisi/lisi)

    登录成功后

    访问admin页面

    总结

    1、localhost:8080 进入登录页面

    2、登录表单提交数据,被UserFormAuthenticationFilter拦截,并创建一个UsernamePasswordToken对象提供给Reaml使用

    3、UserAuthorizingRealm的认证方法doGetAuthenticationInfo接受到token,进行登录认证操作

    认证失败:返回到UserFormAuthenticationFilter的onLoginFailure方法
    
    认证成功:后返回UserFormAuthenticationFilter的issueSuccessRedirect方法
    

    4、如果在用户操作系统过程中访问到了需要权限才能操作的功能(连接、方法、页面等等),就会触发UserAuthorizingRealm中的受权方法doGetAuthorizationInfo进行当前用户的受权操作

  • 相关阅读:
    matlab线性规划
    matlab中fminbnd函数求最小或者组大值
    正方形和球体,利用蒙特卡洛计算pi值
    python 利用cvxopt线性规划
    K-NN(最近邻分类算法 python
    序列匹配,动态规划
    Block中修改局部变量的值为什么必须声明为__block类型
    iOS之初始化对象
    iOS对象模型学习
    C++对象模型学习
  • 原文地址:https://www.cnblogs.com/tandi19960505/p/9678095.html
Copyright © 2011-2022 走看看