智能商贸day3权限验证

                  Shiro

shiro介绍: Shiro是一个强大且易用的Java安全框架,身份验证授权密码学会话管理

Spring security 重量级安全框架(配置很麻烦 做的比较细)

Apache Shiro轻量级安全框架 (配置很容易 很方便,很容易使用)

 

shiro使用的地方:用户登录和登录权限验证

shiro入门:

导包:<dependencies>
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-core</artifactId>
        <version>1.4.0</version>
    </dependency>
    <dependency>
        <groupId>commons-logging</groupId>
        <artifactId>commons-logging</artifactId>
        <version>1.2</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
</dependencies>

准备资源文件:shiro.ini文件

 

 

[users]
# 用户 'root' 密码是 'secret' and the 'admin' 角色
root = secret, admin
# 用户 'guest' 密码 'guest' 和'guest'角色
guest = guest, guest
# user 'presidentskroob' with password '12345' ("That's the same combination on
# my luggage!!!" ;)), and role 'president'
presidentskroob = 12345, president
# 用户 'darkhelmet' with password 'ludicrousspeed' and 角色 'darklord' and 'schwartz'
darkhelmet = 123, darklord, schwartz
# 用户 'lonestarr' 密码 'vespa' and roles 'goodguy' and 'schwartz'
lonestarr = vespa, goodguy, schwartz

[roles]
# 'admin' role has all permissions, indicated by the wildcard '*'
admin = *
# 这个 'schwartz' 角色 能干lightsaber下面的所有事情:
schwartz = lightsaber:*
# goodguy这个角色 能干winnebago下面的drive权限,操作eagle5这个资源 user:delete:5
goodguy = winnebago:drive:eagle5

 

测试登录验证的权限:

//读取到shiro.ini文件,并且根据文件创建SecurityManager对象
// SecurityManager:权限的核心管理对象
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
SecurityManager securityManager = factory.getInstance();

// 为了程序正常运行,需要设计一个这个securityManager(相当于把这个管理放到环境中去了)
SecurityUtils.setSecurityManager(securityManager);

//拿到当前用户【Subject:操作当前系统的一个用户】
Subject currentUser = SecurityUtils.getSubject();

//拿到一个会话(它在咱们的所有类型系统都可以使用【不要求必需是web项目】)
Session session = currentUser.getSession();
//会话操作【可以在会话中设置值与获取值】
session.setAttribute("someKey", "123456");
String value = (String) session.getAttribute("someKey");
if (value.equals("123456")) {
System.out.println("可以获取到这个值"+value);
}

//判断这个用户是否经过验证(没有登录我们可以认为是一个游客)
//没有登录,我们就可以完成登录
if (!currentUser.isAuthenticated()) {
//拿到用户名与密码令牌【拿到用户名与密码】
UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");
//设置记住我的功能
token.setRememberMe(true);
try {
//完成登录功能
currentUser.login(token);
} catch (UnknownAccountException uae) {
//log.info("There is no user with username of " + token.getPrincipal());
//token.getPrincipal()[ˈprɪnsəpl] -> 拿到主体(登录用户的主要标识【用户名】)
System.out.println("这没有这个账号(用户名)"+token.getPrincipal());
} catch (IncorrectCredentialsException ice) {
//incorrect [ˌɪnkəˈrekt]:不正确的,错误的
//Credentials[krəˈdenʃlz]:证书; 凭证,证件
//log.info("Password for account " + token.getPrincipal() + " was incorrect!");
System.out.println("这个密码是错误的"+token.getPrincipal());
} catch (LockedAccountException lae) {
System.out.println("这个账号已经被锁定");
}
//其它的登录失败异常【它是所有登录异常的父类】
catch (AuthenticationException ae) {
//unexpected condition? error?
}
}

//用户登录成功
log.info("User [" + currentUser.getPrincipal() + "] logged in successfully.");

//判断这个用户是否是某一个角色
if (currentUser.hasRole("schwartz")) {
log.info("May the Schwartz be with you!");
} else {
log.info("Hello, mere mortal.");
}

//测试用户是否有某一个权限
if (currentUser.isPermitted("lightsaber:wield")) {
log.info("You may use a lightsaber ring. Use it wisely.");
} else {
log.info("Sorry, lightsaber rings are for schwartz masters only.");
}

//a (very powerful) Instance Level permission:
if (currentUser.isPermitted("winnebago:drive:eagle5")) {
log.info("You are permitted to 'drive' the winnebago with license plate (id) 'eagle5'. " +
"Here are the keys - have fun!");
} else {
log.info("Sorry, you aren't allowed to drive the 'eagle5' winnebago!");
}

//登出(注销当前登录用户)
currentUser.logout();

System.exit(0);//退出虚拟机

自定权限验证:

 

1.首先一个类去继承AuthorizingRealm类会实现两个方法

 

//权限验证方法

 

 

 

protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}

//用户名验证方法
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
return null;
}

 

 

 

用户验证测试//身份认证
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//得到令牌这个authenticationToken就是UsernamePasswordtoken
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
//或得用户主体
Object principal = token.getPrincipal();
//获取前台传送的进来的用户名这个用户名是传过来的
String username = token.getUsername();
//这里根据用户名去获取密码
String password = getByName(username);
if(password==null){
return null;
}
else{
//账号密码传过来与自己的数据库进行比对
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(username, password,null, getName());
return simpleAuthenticationInfo;
}

}
//这里根据用户名去获取密码
public String getByName(String username){
//后台的用户名和前台的进行对比如果过相等就返回123不等就返回null
if("haoge".equals(username)){
return "123";
}else{
return null;
}
}

 

 

 

 

 

//权限认证
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//拿到用户信息
String primaryPrincipal = (String)principalCollection.getPrimaryPrincipal();
//从数据库中拿到用户的权限
Set<String> roles = getRoleByPrincipal(primaryPrincipal);
//从数据库中去拿到用户的角色信息
Set<String> permissions = getPermissionByPrincipal(primaryPrincipal);

SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
//设置获取角色
simpleAuthorizationInfo.setRoles(roles);
//设置获取的权限
simpleAuthorizationInfo.setStringPermissions(permissions);
//返回simpleAuthorizationInfo对象
return simpleAuthorizationInfo;
}

//模拟数据权限想信息
private Set<String> getPermissionByPrincipal(String primaryPrincipal) {
Set<String> permissions = new HashSet<String>();
if("haoge".equals(primaryPrincipal)){
//如果账号密码正确,就返回全部权限
permissions.add("driver:*");
return permissions;
}else{
return null;
}
}
//模拟数据库角色信息
private Set<String> getRoleByPrincipal(String primaryPrincipal) {
//创建一个集合
Set<String> roles = new HashSet<String>();
if("haoge".equals(primaryPrincipal)){
roles.add("admin");
return roles;
}else{
return null;
}
}

 

 

 

 

 

测试类:

 

 

 

@Test
public void test()throws Exception{
//获取自定义验证对象
MyRealm myRealm = new MyRealm();
//得到SecutiryManager 核心对象
DefaultSecurityManager securityManager = new DefaultSecurityManager();
//把自定义验证放进核心对象里面
securityManager.setRealm(myRealm);
//设置到shiro的环境里面 才能运行
SecurityUtils.setSecurityManager(securityManager);
//拿到游客对象
Subject currentUser = SecurityUtils.getSubject();

//创建令牌给出前台的数据
UsernamePasswordToken token = new UsernamePasswordToken("haoge","123","primaryPrincipal");
try {
//游客对象登录传数据进去
currentUser.login(token);
System.out.println("登陆成功");
} catch (UnknownAccountException e) {
e.printStackTrace();
System.out.println("账号不存在");
}catch (IncorrectCredentialsException e) {
e.printStackTrace();
System.out.println("密码出问题..");
}catch (AuthenticationException e) {
e.printStackTrace();
System.out.println("其他认证错误");
}
if(currentUser.hasRole("admin")){
System.out.println("这个用户有admin角色");
}else{
System.out.println("没有角色");
}

if ( currentUser.isPermitted("lightsaber:*")) {
System.out.println("该角色具有lightsaber这个权限");
}else{
System.out.println("没有权限");
}

currentUser.logout();//退出
}

 

密码加密功能:

 

 

@Test
     public void testMyRealm() throws Exception{
         //创建自己定义的Realm
         MyRealm myRealm = new MyRealm();
        //Realm放到securityManager中去
         DefaultSecurityManager securityManager = new DefaultSecurityManager();
         securityManager.setRealm(myRealm);
         //把权限管理器放到相应的环境中(我们可以在项目任何位置拿到)
         SecurityUtils.setSecurityManager(securityManager);


         //设置咱们Realm的密码匹配器(我们的密码要怎么处理)
         HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
         matcher.setHashAlgorithmName("md5"); //匹配器使用MD5的算法
         matcher.setHashIterations(10);//加密算法要迭代多少次
         myRealm.setCredentialsMatcher(matcher);

         //拿到当前用户(Subject就是当前用户,游客)
         Subject currentUser = SecurityUtils.getSubject();
         //准备登录的令牌(准备用户名与密码) -> 这里的密码进行了加密
         UsernamePasswordToken token = new UsernamePasswordToken("admin","123456");

         try {
             //根据令牌进行功能登录(当前用户进行登录)
             currentUser.login(token);
             System.out.println("登录成功啦。。。。");
         } catch (UnknownAccountException e) {
             System.out.println("这个账号不存在!" + token.getPrincipal());
             e.printStackTrace();
         } catch (IncorrectCredentialsException ice) {
             System.out.println("这个密码不存在!" + token.getPrincipal());
             ice.printStackTrace();
         }catch (AuthenticationException e){
             System.out.println("i don't k");
         }
     }

 

 

自定义Reaml加上盐值:

 

//进行登录的认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
    //明显的知道:这个authenticationToken就是UsernamePasswordtoken
    UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken;
    String username = token.getUsername(); //拿到用户名(:这个用户名是传过来的)

    //这里根据用户名去获取密码(如果没有获取到,相当于这个用户不存在,就返回陪我)
    String password = getByName(username);
    if(password==null){
        return null;
    }
    //在这里加盐值需一个ByteSource对象,而Shiro提供了一个ByteSource对象给咱们
    ByteSource salt = ByteSource.Util.bytes("itsource");
    //创建一个简单的身份信息(把用户名与密码放进去-注:它会自动的比较获取的密码与你传过来的密码)
    SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(username,password,salt,getName());
    return authenticationInfo;
}

private String getByName(String username) {
    if("admin".equals(username)){
        // 4a95737b032e98a50c056c41f2fa9ec6: 123456 迭代10次不加盐的结果
        // 831d092d59f6e305ebcfa77e05135eac: 123456 迭代10次加盐(itsource)的结果
        return "831d092d59f6e305ebcfa77e05135eac"; //修改为加密加盐后的数据
    }else if("guest".equals(username)){
        return "abcd";
    }
    return null;
}

 

 

Shiro集成Spring:我们的项目基本都是通过Spring来管理bean的,如果要想使用Shiro,那就要把shiro集成到Spring。集成Spring的核心就是把shiro框架的核心类(SecurityManager,Subject,Realm)交给Spring管理

导入集成的包: <dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-all</artifactId>
    <version>1.4.0</version>
    <type>pom</type>
</dependency>
  <!-- shiroSpring的集成包 -->
  <dependency>

    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring</artifactId>
    <version>1.4.0</version>
  </dependency>
web.xml配置文件:

<filter>
  <filter-name>shiroFilter</filter-name>
  <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
  <init-param>
    <param-name>targetFilterLifecycle</param-name>
    <param-value>true</param-value>
  </init-param>
</filter>

<filter-mapping>
  <filter-name>shiroFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>


配置过滤器:

<!-- 1.配置apache的管理器 -->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <!-- 配置一个realm,到数据库中获取权限数据 -->
        <property name="realm" ref="jpaRealm"/>
    </bean>


    <!-- 2.我们可以自定义一个realm【暂时未实现功能】这个必需实现org.apache.shiro.realm.Realm接口 -->
    <bean id="jpaRealm" class="cn.itsource.yxb.shiro.realm.JpaRealm">
    </bean>

    <!-- 3.lifecycleBeanPostProcessor:可以自动调用在Spring Ioc窗口中 Shiro bean的生成周期方法 -->
    <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
    <!-- 4.启动ioc容器中使用 shiro的注解,但是必需配置在Spring Ioc容器中Shiro bean的生成周期方法 -->
    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
          depends-on="lifecycleBeanPostProcessor"/>
    <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
        <property name="securityManager" ref="securityManager"/>
    </bean>

    <!-- 5.shiro的真实过滤器(注:这个名称必需和web.xml的代表过滤器【DelegatingFilterProxy】名称一样) -->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <property name="securityManager" ref="securityManager"/>
        <!-- 登录的url,如果没有登录,你访问的路径会跳到这个页面 -->
        <property name="loginUrl" value="/s/login.jsp"/>
        <!-- 登录成功的url,如果登录成功,会跳转到这个页面 -->
        <property name="successUrl" value="/s/main.jsp"/>
        <!-- 没有权限时跳转到这个位置 -->
        <property name="unauthorizedUrl" value="/s/unauthorized.jsp"/>
        <!--
            配置哪些资源被保护,哪些资源需要权限
            anon:不需要登录也可以访问相应的权限
            authc:需要权限才能访问
              /** :所有文件及其子文件
        -->
        <property name="filterChainDefinitions">
            <value>
                /s/login.jsp = anon
                /** = authc
            </value>
        </property>
    </bean>










 

猜你喜欢

转载自www.cnblogs.com/1999wang/p/11312314.html